The functions in the new ng-restr.cc are "pure": They don't access global state; data is passed in via the new and incomplete newgame_def.
Eventually, new_game should be split into something like newgame_def choose_game(); that doesn't access "you", and void setup_game(newgame_def); that sets up the player.
Also get rid of player_size in favour of player::body_size. Rename player_size_type to size_part_type since it's not really player-specific (used in actor::body_size). Move parts of player_genus, player::has_claws, body_size out into species.cc.
77KQMSMPKSU2HXCP5UDQJOM6ETXFCF2IYFM2EU566D5A7XE7AHKQC
Q2DRRRBRUB5YD6RC7J73CIIA4566TTGOWDHKPRALBVWFYEZKEUSQC
75JWS3AAH2VYNUJO3HM54T3XUBQQX75RI5NARFF6AYTABOPXUPHAC
VCCUMZF3AVNPDNGZZUBOPVY4EUYGE4BM3CS7MUSMMEUZ5CIMPJ6AC
ZZPIS557ACG3GKJORIG4ITIH7EYAJJECFWERKEGA7Q4M7OIRKXCAC
OLS6D34F57OHGMA25CFXWZ3KEIA47M3XBTBSY4RWMTVNEYKX6X7AC
IJXKGFW3SSADXDWHBFA4TOW74RLVJAWKBHZ245KG64LHHJFCC6XAC
NEQMKAUYFAGS3M44REOZXBBGSLM5KJBY4PSXIKUBM7J5BRD2AMDAC
HHEXCJDIFUD4LO2TJWRW6UAXK3XMKCIGMFOFJZFB3YAYSFUAMPQAC
P7DI6TRDWFXMNCBFI5WKPFXVB7PLW7JAJSL2HWC25I6YEWBUC4OAC
6ZDCG4JTGE6VQO755P4COB2BW2STIBVL2LX7EPBGP4JE54AIJKYQC
IL4WCJVROF4HKGUQLIRWIMXL2SCULU43PAE5D7U5V6EXLB52DO6QC
ASXBSZVXJCWVX5VQSRWXL5BWQ4NA7JLYXP6LWQTRGYW6DC2DZZPQC
M7THNJTZZ2MRBFR7XZWIR7WZLL6PFXBDQNYKTRWNUNIFQSSVZOPQC
SNH6UWOYVWP4A6B4NC6YZ6KRYPYCGGNYCW5TILTALPH552H2EUFQC
DIAGORS5MPTNYDMPDOBXCIGCVDH7THTHYFOQUKMET57QH2J6WF5AC
WRDCASRSGOBY5RLVORAMRBSYKEWLLO7VZ4V5NQG2TKBWYNU4OZKAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
CLIEHAE2PP7ZIGLLIMYCWM4FC54KBOAN5AILOLAZJ5S26GTJM4RQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
DKRSOHZXL6EPSLKOKHF7GJXSZEJVY7CXGACSHWLM5B5FTRETWWCAC
5WKKONCYM73GBJ6GDYK3OLZ2PB7KJHFDYGEMHQQMPQMFJJHTLWCQC
LDFSITXKT52MLJJYOKDEFNLOEYIIV4ZOZHFH3U7PYSUNKF2KBIVQC
QIHESOUNY5H7T56DAVXJMZRBUJPDMLHGTM34WIMPCWSUM72Z6QPQC
M5ZDZJBTOJ7SWQPZZQPC24JYZKP26MWSRDHXBWQE2MPPL6WCXOIQC
VJZ4D26E4L4E22SO6UYB44DNUTLG72LA4GTAEZ2DKKEMAICHOXBQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
YN7KNAJU72XINIQ3GP7RJLKW3STMN5VWJV2K66ICPZXR2VMYLZPAC
S6ADNAPM545WP3FRHCU6UWKX5VEMY5TPSIZYSZ3XE76VCBTVIN5QC
3GJTOMYXXJLY7QZNJLIONXAOHMU64PDYRXUYYQATIB7WPRHSNN6AC
3BYA46OYLVN6ZPGAZD5OGIMMH5PRWGNSU3ITJRCVBE6P5HYYYAYQC
ADIVVYTV2MJ3XVRYDNBLPTAEACCNF27XZDCRVZFQEHRHPMZGNITQC
A3O24OMWTAW7EHB4T7HYAMW6MXINAWHEHV6LWZI6XS3GGFWSWZQAC
FKQ4AQKB2XXAQQFMNPUQCT6FD54NM5JVWABBPT26HKKQPPWB7XUAC
VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC
KKJUHD576DZVDDQ7JFBAO7S35DAPIMZNOYVLAUBDOTTUGR4Q53JQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
ILO5P5FRDUY4SEQEXMTUDKOPXAUBJRSORHHUVTLLCYOYSXBXOVRAC
3V52MSSK7QX7FWLLUW63DTWCBAJEK674EFZLKP45FLZ5KZKVARHAC
5LDEEBB7DT4CORJZOAYLQFXNI7FOURUJGAKVDVX7YL745NNRW63AC
DIL5CIV3FGFPRSMRAGDDOHBJ2MBIOEZNMDDTJ4MYI7CU6BYAFVUAC
UVJBHQ5KGUIEFRHKTYQPKSXYDUDKTRAXINUXGJJJ6QGNCR6JO7ZAC
5WOIUTOWIGPY64XLGDFHYJZUJCHUBHKDBYY3ZHMD4JDAJ7KHPMDAC
MXXDHHK4X5OHJ24JK6LSWZOSN7GMKOERH2LR27Z6LLLG2QECLYPAC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
JDM5R3HYGXKQKZWY35QZ2KOB24TFZ3FW2PCNXCRCMWG72AZC5ZXQC
WN3ZHNL4T7QMQC6JF5DJR6NHLZVOGQVO4OJNEKEM5FZKQ7AVOP4AC
S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC
C2PRXJYHDRF2642VDAUY76HJKCPQFGWDI6AM3SMCMYCHGWYDQXQQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
PNRMCHHEBCAUD2XBSSH6JOEQ6A6CFEZBCIX436DVD26DA52OCYTQC
LY2CUJ262FHANYCRHMGFEUBVPBHMA5FJHAUALAU6WVZGJSJ6YELQC
RGWUYJO74FDGTH22CYSHBKFDGJ4S76WTLIULKPXA4QT5ZCNOB4LQC
LABXKXWWQY2V4FUDLGVTDYHXINAP6KRHZDHBQ2FE22FFOEIZPL6QC
JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC
S4BRP4VHB23F2FCC6BXNAN2MZRVUGW7QMXUEOAVZVGFXKXJPVLLQC
5LVPHV2K57SCC7S4PECZOHPPQOIY5S7N6QBPAHK7IZLYV6NQQC7QC
33MBISZXMRGZMQ37PVINHKNWAXHYPHURMRG6ST7O2SKIRGGBHI2AC
YPL32ZYVNBA2OSLEUGSAGSDJ5U2NKYMUHOL7GYSE2F4FCFZI2PTAC
WAO43LWOVQKOXAKIML5ZA6UKSORMPXAMGYFPRVK2DNMQSPLC5JGQC
XYQFJLTMLSU7LC7VODUJVN5F2P47STH2KVSP7Q3BSCUUDRHROW7QC
QY5XETDODOIIOMYH4AKVORUYMMYG5WSDFUIDZI6NRFEEQWXI55UAC
OHOFJZ6S5AJUO5EFVGG7HJHRPSXJSTJD2DDXAERT4LNVWDK23K6AC
WMFU65IAJ3LX2YSFXXRS7ZFNDCZYQC3ZQ3QDHHK3DU3UMLJMAP4QC
QWIGHBYDCRD4VSUAY4GAPS66VM2JGMYMLPHWK6A6BCVPUXU7W5WQC
WUCXHWMF2FL5KCC6E6KNKMYL2NBXXC3WVRY2AUPWSBAPWJFGS34QC
GUXTGUEMZYBRGV5QUAQSJHG3AOIQDWWCDIMOX4LASFJAZVGL2WQAC
3FRPKD2JSN7RA2HKWAO3XV7MMKCIAMWIMU6JNJ452VZEUSXM6PWQC
ORZ37JMK7WY6FLTYZGC75D3POVCAZMZ7RCZIY4ZL2EGPXBMBCKJQC
RWSXCNYUGDSMP2GKN22HROC5Q2GHSAVJJUDRT3Z53WU2DAI4IZOQC
VGKONTCFVUJKMGHHKIUBSMTYHWH7776H5HUJ74XV7NLK3TCGIZPAC
PO3IATZV4JX3I3522UAGF53ZLZ4FW7C2J32Z23PEWQVHGGEUO7SAC
ES6J64POV7ONJRA4GVMPMVS7JKZZEXHE64BQAOOASMJDUPM7OKWAC
JPGW2YFZDRPAWPG4VAKOOB5SCJA2QSSLR5JJP7ULRBX3LLGI7PUAC
Z5QBJXLFUTXIHT4ADRMK7M33GX2DCDN323QQKYHWGYJ7GQKWW3TAC
B5OK4FEITJ6MUT7J76OJJH2TOPTZGG7J7UPIJ6Z6WA5FC526FLTAC
MCQZ4HEOF65FEVWUEAMO2765JYMJPKXQ454HCCWWK3JUYEUSUXTAC
G5CA5STLILMQZO2ICHZTVTW76V6RMC7KWP4ELU7ANZBNXYSTWV7AC
Y35JUXHENHI4INSFP2UO4ZJLJJFC7WDDC7LR4HZZHR73FKQB4DXQC
FS732HH3GBQCSQRKU5ZYBYVLDBGOAGBWDNKHQV5HETPT634CFLDAC
M6IHSU5JWCTOTUSPCVVHMAQ4XJDGQJOLZTTN5BGKEOS4B6Z7IOWAC
2VI52BHBTTER5YTZVPZNAOKVNXFJAJ6XLYXTFWCBWEBDFNJ7PWDAC
HCQBAKIE4MXJ3XID6CECTZGNWYC33C3642KOKNKO37VVRDMJ2T4QC
2DZ57LMGON6GPOAGZAWNXQPFMPGGZOMZJO62GQBDECNM5KIOC6OQC
BTDIRPAGSX5DWEEV62VGTYALWM6G5LKFKHT7HYJXVH7XBA4BPHLQC
3RY3A4K3ZCAJ235ID3ZDKFWYSYFD42AZOVAKL6767D5GH2QJTCPQC
UKYGZDI6PYZPXDACCQGVPHANUP5ADCSNROOZIE7LYIZQWSNFHJZAC
LCDAVMTTCXQW6AOXG4IHXGRGVNMA47ZKHXW3NDYK2YFJFBMCFFQAC
YXWZYOBUFR4EHBSKXCFGZNK7NIM7IPE2GMZYIXEJTUPDDC3BIEDAC
QHABWX5UYQAREZC4B6JGSRXSUH6DQLRD7WB4YGV4HHUHMTXY3ERAC
3U54KX4JPCEBGC3USUQJVX35HBEWV6DX6ZZ4RV7GT3HBX7LMLKPAC
C67GX7W5HBCDPQJRSHWMLM4DUJ3ELFSHH42SVICFJVCJW25T5Z3AC
MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC
K4ZO7CVDWUJRLGMBQDDLHOVT45DWZQWINRQGWPWP4DLYKVD3672AC
3UUTHUKEJVRCYSOE3S3W423SADYD22L3DUXFB6CAFDVM66EPIF7AC
YJ4Q65CCPG2R3O2CFICU6WS27ISYEHQGWIHNOOYPN2TIPKNXVX7QC
4FQAKUKUO6PCAZ3N4HUR5XL6E4VA5UQUZ3AEDGRBLVY7W2LMWI7QC
R4KOJ7NY3HSBUCXYLNGBA7REIEKBIQBYQE5HTPFCMVWLMNBYYPWAC
26ACPNDHIMNMT5RV3GML6RTSVILQHVURAFL2JZR4O6AC5OXE7JHAC
GAYW6ZERQLVVVZ6ZT7QUHA3MUETUBWNRSEE22DO4T7MWL7NBIPAAC
3EUPIYJNWOMOQBP2Z5SGSMWK453BXJD6KL2WFTR3NM565MEBYASAC
SUWIERONPDATHPDMZRYO6GYIXSW6XIS5V5MK5IV23DWQH2LL7VIAC
MBTH7A4NYIRD3T64ASJI2HOMUQ42BGOVTQXTKM5DLHMUQMM7H5FAC
PI5BATR2SER3RFE76IUGHM2AGXVFOUM3PLU7WC2K2Q2BA5K2E73QC
SHFSQYLN7WPQC35V3XYYEIZ4CQMREASUNR474CIKFG3C2FYI4SHQC
7BBEAPSUBQMBK4XC2Q6YJ2JPSVSPCSBJUYXM6EWXHNTQG4AEJX3QC
M2FQTQ5MGAOKGIN4RSMF6RYT7WB4PVLMWFIY7S5IU5LB6DIWZSBQC
}
int species_has_claws(species_type species)
{
if (species == SP_TROLL)
return (3);
if (species == SP_GHOUL)
return (1);
return (0);
}
genus_type species_genus(species_type species)
{
switch (species)
{
case SP_RED_DRACONIAN:
case SP_WHITE_DRACONIAN:
case SP_GREEN_DRACONIAN:
case SP_YELLOW_DRACONIAN:
case SP_GREY_DRACONIAN:
case SP_BLACK_DRACONIAN:
case SP_PURPLE_DRACONIAN:
case SP_MOTTLED_DRACONIAN:
case SP_PALE_DRACONIAN:
case SP_BASE_DRACONIAN:
return (GENPC_DRACONIAN);
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
return (GENPC_ELVEN);
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
return (GENPC_DWARVEN);
case SP_OGRE:
return (GENPC_OGRE);
default:
return (GENPC_NONE);
}
}
size_type species_size(species_type species, size_part_type psize)
{
switch (species)
{
case SP_OGRE:
case SP_TROLL:
return (SIZE_LARGE);
case SP_NAGA:
// Most of their body is on the ground giving them a low profile.
if (psize == PSIZE_TORSO || psize == PSIZE_PROFILE)
return (SIZE_MEDIUM);
else
return (SIZE_LARGE);
case SP_CENTAUR:
return ((psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE);
case SP_SPRIGGAN:
return (SIZE_LITTLE);
case SP_HALFLING:
case SP_KOBOLD:
return (SIZE_SMALL);
default:
return(SIZE_MEDIUM);
}
bool is_valid_species(species_type species)
{
return (species >= 0 && species < NUM_SPECIES);
}
switch (species)
{
case SP_RED_DRACONIAN:
case SP_WHITE_DRACONIAN:
case SP_GREEN_DRACONIAN:
case SP_YELLOW_DRACONIAN:
case SP_GREY_DRACONIAN:
case SP_BLACK_DRACONIAN:
case SP_PURPLE_DRACONIAN:
case SP_MOTTLED_DRACONIAN:
case SP_PALE_DRACONIAN:
case SP_BASE_DRACONIAN:
return (which_genus == GENPC_DRACONIAN);
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
return (which_genus == GENPC_ELVEN);
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
return (which_genus == GENPC_DWARVEN);
case SP_OGRE:
return (which_genus == GENPC_OGRE);
// psize defaults to PSIZE_TORSO, which checks the part of the body
// that wears armour and wields weapons (which is different for some hybrids).
// base defaults to "false", meaning consider our current size, not our
// natural one.
size_type player_size(int psize, bool base)
{
return you.body_size(psize, base);
}
// XXX: player_size() implementations are incomplete, fix.
const size_type size = player_size(PSIZE_BODY);
const size_type torso = player_size(PSIZE_TORSO);
// XXX: you.body_size() implementations are incomplete, fix.
const size_type size = you.body_size(PSIZE_BODY);
const size_type torso = you.body_size(PSIZE_TORSO);
// Transformation has size of character's species.
switch (species)
{
case SP_OGRE:
case SP_TROLL:
ret = SIZE_LARGE;
break;
case SP_NAGA:
// Most of their body is on the ground giving them a low profile.
if (psize == PSIZE_TORSO || psize == PSIZE_PROFILE)
ret = SIZE_MEDIUM;
else
ret = SIZE_LARGE;
break;
case SP_CENTAUR:
ret = (psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE;
break;
case SP_SPRIGGAN:
ret = SIZE_LITTLE;
break;
case SP_HALFLING:
case SP_KOBOLD:
ret = SIZE_SMALL;
break;
default:
ret = SIZE_MEDIUM;
break;
}
size_type tf_size = transform_size(psize);
return (tf_size == SIZE_CHARACTER ? species_size(species, psize)
: tf_size);
// these are the only other sources for claws
if (species == SP_TROLL)
return (3);
if (species == SP_GHOUL)
return (1);
// XXX: Some assumptions about mutations and species in here.
int sp_claws = species_has_claws(species);
if (sp_claws > 0)
return (sp_claws);
#ifndef NG_RESTR_H
#define NG_RESTR_H
#include "newgame.h"
enum char_choice_restriction
{
CC_BANNED = 0,
CC_RESTRICTED,
CC_UNRESTRICTED
};
char_choice_restriction class_allowed(species_type speci,
job_type char_class);
bool is_good_combination(species_type spc, job_type cls,
bool good = false);
char_choice_restriction book_restriction(startup_book_type booktype,
const newgame_def &ng);
char_choice_restriction weapon_restriction(weapon_type wpn,
const newgame_def &ng);
char_choice_restriction religion_restriction(god_type god,
const newgame_def &ng);
#endif
/*
* File: ng-restr.cc
* Summary: Character choice restrictions.
*
* The functions in this file are "pure": They don't
* access any global data.
*/
#include "AppHdr.h"
#include "ng-restr.h"
#include "newgame.h"
#include "species.h"
#include "jobs.h"
char_choice_restriction class_allowed(species_type speci,
job_type char_class)
{
switch (char_class)
{
case JOB_FIGHTER:
switch (speci)
{
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_OGRE:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_GLADIATOR:
switch (speci)
{
case SP_DEEP_ELF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_TROLL:
case SP_RED_DRACONIAN:
case SP_GHOUL:
case SP_MUMMY:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_MONK:
switch (speci)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_RED_DRACONIAN:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_BERSERKER:
switch (speci)
{
case SP_DEMIGOD:
return (CC_BANNED);
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_PALADIN:
switch (speci)
{
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_OGRE:
case SP_TROLL:
case SP_KENKU:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_PRIEST:
switch (speci)
{
case SP_DEMIGOD:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_OGRE:
case SP_TROLL:
case SP_KENKU:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_CHAOS_KNIGHT:
switch (speci)
{
case SP_DEMIGOD:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_KENKU:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_DEATH_KNIGHT:
switch (speci)
{
case SP_SPRIGGAN:
case SP_NAGA:
case SP_KENKU:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_HEALER:
switch (speci)
{
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_NAGA:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_CRUSADER:
switch (speci)
{
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_REAVER:
switch (speci)
{
case SP_HUMAN:
case SP_SLUDGE_ELF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_WIZARD:
switch (speci)
{
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_OGRE:
case SP_MINOTAUR:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_CONJURER:
switch (speci)
{
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_ENCHANTER:
switch (speci)
{
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_DEMONSPAWN:
case SP_GHOUL:
case SP_MUMMY:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_SUMMONER:
switch (speci)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_RED_DRACONIAN:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_NECROMANCER:
switch (speci)
{
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_WARPER:
switch (speci)
{
case SP_HUMAN:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_TRANSMUTER:
switch (speci)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_FIRE_ELEMENTALIST:
switch (speci)
{
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_ICE_ELEMENTALIST:
switch (speci)
{
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_AIR_ELEMENTALIST:
switch (speci)
{
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_EARTH_ELEMENTALIST:
switch (speci)
{
case SP_HIGH_ELF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_VENOM_MAGE:
switch (speci)
{
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_STALKER:
switch (speci)
{
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_THIEF:
return (CC_RESTRICTED);
case JOB_ASSASSIN:
switch (speci)
{
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_RED_DRACONIAN:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_HUNTER:
switch (speci)
{
case SP_DEEP_DWARF:
case SP_KOBOLD:
case SP_NAGA:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_ARTIFICER:
switch (speci)
{
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_OGRE:
case SP_MUMMY:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_WANDERER:
return (CC_RESTRICTED);
default:
return (CC_BANNED);
}
}
bool is_good_combination(species_type spc, job_type cls, bool good)
{
const char_choice_restriction restrict = class_allowed(spc, cls);
if (good)
return (restrict == CC_UNRESTRICTED);
return (restrict != CC_BANNED);
}
// Is the given book restricted for the character defined by ng?
// Only uses ng.species.
char_choice_restriction book_restriction(startup_book_type booktype,
const newgame_def &ng)
{
ASSERT(is_valid_species(ng.species));
switch (booktype)
{
case SBT_FIRE: // Fire
switch (ng.species)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_HILL_ORC:
case SP_KOBOLD:
case SP_NAGA:
case SP_OGRE:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_UNRESTRICTED);
default:
if (species_genus(ng.species) == GENPC_DRACONIAN)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
break;
case SBT_COLD: // Ice
switch (ng.species)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_KOBOLD:
case SP_NAGA:
case SP_OGRE:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_UNRESTRICTED);
default:
if (species_genus(ng.species) == GENPC_DRACONIAN)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
break;
case SBT_SUMM: // Summoning
switch (ng.species)
{
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_KOBOLD:
case SP_NAGA:
case SP_OGRE:
case SP_KENKU:
case SP_MUMMY:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
return (CC_RESTRICTED);
}
break;
default:
return (CC_RESTRICTED);
}
}
// Is the given god restricted for the character defined by ng?
// Only uses ng.species and ng.job.
char_choice_restriction weapon_restriction(weapon_type wpn,
const newgame_def &ng)
{
ASSERT(is_valid_species(ng.species));
ASSERT(is_valid_job(ng.job));
switch (wpn)
{
case WPN_UNARMED:
if (species_has_claws(ng.species))
return (CC_UNRESTRICTED);
return (CC_BANNED);
case WPN_SHORT_SWORD:
switch (ng.species)
{
case SP_NAGA:
case SP_VAMPIRE:
// The fighter's heavy armour hinders stabbing.
if (ng.job == JOB_FIGHTER)
return (CC_RESTRICTED);
// else fall through
case SP_HIGH_ELF:
case SP_DEEP_ELF:
// Sludge elves have bad aptitudes with short swords (110) but are
// still better with them than any other starting weapon.
case SP_SLUDGE_ELF:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
return (CC_UNRESTRICTED);
default:
return (CC_RESTRICTED);
}
// Maces and hand axes usually share the same restrictions.
case WPN_MACE:
if (ng.species == SP_TROLL)
return (CC_UNRESTRICTED);
if (ng.species == SP_VAMPIRE)
return (CC_RESTRICTED);
// else fall-through
case WPN_HAND_AXE:
switch (ng.species)
{
case SP_HUMAN:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MUMMY:
case SP_CENTAUR:
case SP_NAGA:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
return (species_genus(ng.species) == GENPC_DRACONIAN ? CC_UNRESTRICTED
: CC_RESTRICTED);
}
case WPN_SPEAR:
switch (ng.species)
{
case SP_HUMAN:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_NAGA:
case SP_CENTAUR:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_UNRESTRICTED);
default:
return (species_genus(ng.species) == GENPC_DRACONIAN ? CC_UNRESTRICTED
: CC_RESTRICTED);
}
case WPN_TRIDENT:
if (ng.species != SP_MERFOLK
&& (ng.job != JOB_GLADIATOR
|| species_size(ng.species, PSIZE_BODY) < SIZE_MEDIUM))
{
return (CC_BANNED);
}
// Tridents are strictly better than spears, so unrestrict them
// for some species whose Polearm aptitudes are not too bad.
switch (ng.species)
{
case SP_MOUNTAIN_DWARF:
case SP_OGRE:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
break;
}
// Both are polearms, right?
return (weapon_restriction(WPN_SPEAR, ng));
case WPN_ANKUS:
if (species_genus(ng.species) == GENPC_OGRE)
return (CC_UNRESTRICTED);
// intentional fall-through
default:
return (CC_BANNED);
}
}
// Is the given god restricted for the character defined by ng?
// Only uses ng.species and ng.job.
char_choice_restriction religion_restriction(god_type god,
const newgame_def &ng)
{
ASSERT(is_valid_species(ng.species));
ASSERT(is_valid_job(ng.job));
// Sanity check.
if (ng.species == SP_DEMIGOD)
return (CC_BANNED);
switch (god)
{
case GOD_BEOGH:
if (ng.species == SP_HILL_ORC)
return (CC_UNRESTRICTED);
return (CC_BANNED);
case GOD_ZIN:
switch (ng.species)
{
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_BANNED);
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_MINOTAUR:
case SP_OGRE:
return (CC_UNRESTRICTED);
default:
return (CC_RESTRICTED);
}
case GOD_YREDELEMNUL:
switch (ng.species)
{
case SP_HILL_ORC:
// Restrict in favour of Beogh, else unrestricted.
if (ng.job == JOB_PRIEST)
return (CC_RESTRICTED);
return (CC_UNRESTRICTED);
case SP_DEEP_ELF:
case SP_KENKU:
// Unrestrict these only for Priests as Zin is worse, but
// Necromancy (DK) the better choice.
if (ng.job == JOB_PRIEST)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
if (species_genus(ng.species) == GENPC_DRACONIAN)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
case GOD_XOM:
switch (ng.species)
{
case SP_MOUNTAIN_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMONSPAWN:
return (CC_UNRESTRICTED);
default:
if (species_genus(ng.species) == GENPC_DRACONIAN)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
case GOD_MAKHLEB:
switch (ng.species)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
if (species_genus(ng.species) == GENPC_DRACONIAN)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
case GOD_LUGONU:
switch (ng.species)
{
case SP_HUMAN:
case SP_MOUNTAIN_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_DEMONSPAWN:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
if (species_genus(ng.species) == GENPC_DRACONIAN)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
default:
return (CC_RESTRICTED);
}
}
static char_choice_restriction _class_allowed(species_type speci,
job_type char_class)
{
switch (char_class)
{
case JOB_FIGHTER:
switch (speci)
{
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_OGRE:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_GLADIATOR:
switch (speci)
{
case SP_DEEP_ELF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_TROLL:
case SP_RED_DRACONIAN:
case SP_GHOUL:
case SP_MUMMY:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_MONK:
switch (speci)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_RED_DRACONIAN:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_BERSERKER:
switch (speci)
{
case SP_DEMIGOD:
return (CC_BANNED);
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_PALADIN:
switch (speci)
{
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_OGRE:
case SP_TROLL:
case SP_KENKU:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_PRIEST:
switch (speci)
{
case SP_DEMIGOD:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_OGRE:
case SP_TROLL:
case SP_KENKU:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_CHAOS_KNIGHT:
switch (speci)
{
case SP_DEMIGOD:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_KENKU:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_DEATH_KNIGHT:
switch (speci)
{
case SP_SPRIGGAN:
case SP_NAGA:
case SP_KENKU:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_HEALER:
switch (speci)
{
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_BANNED);
case SP_DEEP_ELF:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_NAGA:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_CRUSADER:
switch (speci)
{
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_REAVER:
switch (speci)
{
case SP_HUMAN:
case SP_SLUDGE_ELF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_WIZARD:
switch (speci)
{
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_OGRE:
case SP_MINOTAUR:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_CONJURER:
switch (speci)
{
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_ENCHANTER:
switch (speci)
{
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_DEMONSPAWN:
case SP_GHOUL:
case SP_MUMMY:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_SUMMONER:
switch (speci)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_RED_DRACONIAN:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_NECROMANCER:
switch (speci)
{
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_WARPER:
switch (speci)
{
case SP_HUMAN:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_TRANSMUTER:
switch (speci)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_FIRE_ELEMENTALIST:
switch (speci)
{
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_ICE_ELEMENTALIST:
switch (speci)
{
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_AIR_ELEMENTALIST:
switch (speci)
{
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_EARTH_ELEMENTALIST:
switch (speci)
{
case SP_HIGH_ELF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_SPRIGGAN:
case SP_NAGA:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_RED_DRACONIAN:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_VENOM_MAGE:
switch (speci)
{
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_HALFLING:
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_STALKER:
switch (speci)
{
case SP_HIGH_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_THIEF:
return (CC_RESTRICTED);
case JOB_ASSASSIN:
switch (speci)
{
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_RED_DRACONIAN:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_HUNTER:
switch (speci)
{
case SP_DEEP_DWARF:
case SP_KOBOLD:
case SP_NAGA:
case SP_RED_DRACONIAN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_ARTIFICER:
switch (speci)
{
case SP_CENTAUR:
case SP_TROLL:
case SP_MINOTAUR:
case SP_OGRE:
case SP_MUMMY:
case SP_GHOUL:
return (CC_RESTRICTED);
default:
return (CC_UNRESTRICTED);
}
case JOB_WANDERER:
return (CC_RESTRICTED);
default:
return (CC_BANNED);
}
}
static bool _is_good_combination( species_type spc, job_type cls, bool good)
{
const char_choice_restriction restrict = _class_allowed(spc, cls);
if (good)
return (restrict == CC_UNRESTRICTED);
return (restrict != CC_BANNED);
}
}
}
static char_choice_restriction _book_restriction(startup_book_type booktype)
{
switch (booktype)
{
case SBT_FIRE: // Fire
switch (you.species)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_HILL_ORC:
case SP_KOBOLD:
case SP_NAGA:
case SP_OGRE:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_UNRESTRICTED);
default:
if (player_genus(GENPC_DRACONIAN))
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
break;
case SBT_COLD: // Ice
switch (you.species)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_KOBOLD:
case SP_NAGA:
case SP_OGRE:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_UNRESTRICTED);
default:
if (player_genus(GENPC_DRACONIAN))
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
break;
case SBT_SUMM: // Summoning
switch (you.species)
{
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_KOBOLD:
case SP_NAGA:
case SP_OGRE:
case SP_KENKU:
case SP_MUMMY:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
return (CC_RESTRICTED);
}
break;
default:
return (CC_RESTRICTED);
static char_choice_restriction _weapon_restriction(weapon_type wpn)
{
switch (wpn)
{
case WPN_UNARMED:
if (you.has_claws())
return (CC_UNRESTRICTED);
return (CC_BANNED);
case WPN_SHORT_SWORD:
switch (you.species)
{
case SP_NAGA:
case SP_VAMPIRE:
// The fighter's heavy armour hinders stabbing.
if (you.char_class == JOB_FIGHTER)
return (CC_RESTRICTED);
// else fall through
case SP_HIGH_ELF:
case SP_DEEP_ELF:
// Sludge elves have bad aptitudes with short swords (110) but are
// still better with them than any other starting weapon.
case SP_SLUDGE_ELF:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
return (CC_UNRESTRICTED);
default:
return (CC_RESTRICTED);
}
// Maces and hand axes usually share the same restrictions.
case WPN_MACE:
if (you.species == SP_TROLL)
return (CC_UNRESTRICTED);
if (you.species == SP_VAMPIRE)
return (CC_RESTRICTED);
// else fall-through
case WPN_HAND_AXE:
switch (you.species)
{
case SP_HUMAN:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MUMMY:
case SP_CENTAUR:
case SP_NAGA:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
return (player_genus(GENPC_DRACONIAN) ? CC_UNRESTRICTED
: CC_RESTRICTED);
}
case WPN_SPEAR:
switch (you.species)
{
case SP_HUMAN:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_NAGA:
case SP_CENTAUR:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMIGOD:
case SP_DEMONSPAWN:
case SP_MUMMY:
return (CC_UNRESTRICTED);
default:
return (player_genus(GENPC_DRACONIAN) ? CC_UNRESTRICTED
: CC_RESTRICTED);
}
case WPN_TRIDENT:
if (you.species != SP_MERFOLK
&& (you.char_class != JOB_GLADIATOR
|| player_size(PSIZE_BODY) < SIZE_MEDIUM))
{
return (CC_BANNED);
}
// Tridents are strictly better than spears, so unrestrict them
// for some species whose Polearm aptitudes are not too bad.
switch (you.species)
{
case SP_MOUNTAIN_DWARF:
case SP_OGRE:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
break;
}
// Both are polearms, right?
return (_weapon_restriction(WPN_SPEAR));
case WPN_ANKUS:
if (player_genus(GENPC_OGRE))
return (CC_UNRESTRICTED);
// intentional fall-through
default:
return (CC_BANNED);
}
}
// Gods are not restricted but there are some choices that are banned (false).
// Everything else will be unrestricted.
static char_choice_restriction _religion_restriction(god_type god)
{
// Sanity check.
if (you.species == SP_DEMIGOD)
return (CC_BANNED);
switch (god)
{
case GOD_BEOGH:
if (you.species == SP_HILL_ORC)
return (CC_UNRESTRICTED);
return (CC_BANNED);
case GOD_ZIN:
switch (you.species)
{
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_BANNED);
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_MINOTAUR:
case SP_OGRE:
return (CC_UNRESTRICTED);
default:
return (CC_RESTRICTED);
}
case GOD_YREDELEMNUL:
switch (you.species)
{
case SP_HILL_ORC:
// Restrict in favour of Beogh, else unrestricted.
if (you.char_class == JOB_PRIEST)
return (CC_RESTRICTED);
return (CC_UNRESTRICTED);
case SP_DEEP_ELF:
case SP_KENKU:
// Unrestrict these only for Priests as Zin is worse, but
// Necromancy (DK) the better choice.
if (you.char_class == JOB_PRIEST)
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
if (player_genus(GENPC_DRACONIAN))
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
case GOD_XOM:
switch (you.species)
{
case SP_MOUNTAIN_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_KENKU:
case SP_DEMONSPAWN:
return (CC_UNRESTRICTED);
default:
if (player_genus(GENPC_DRACONIAN))
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
case GOD_MAKHLEB:
switch (you.species)
{
case SP_HUMAN:
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
case SP_MOUNTAIN_DWARF:
case SP_DEEP_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_HALFLING:
case SP_KOBOLD:
case SP_NAGA:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_DEMONSPAWN:
case SP_MUMMY:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
if (player_genus(GENPC_DRACONIAN))
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
case GOD_LUGONU:
switch (you.species)
{
case SP_HUMAN:
case SP_MOUNTAIN_DWARF:
case SP_HILL_ORC:
case SP_MERFOLK:
case SP_SPRIGGAN:
case SP_CENTAUR:
case SP_OGRE:
case SP_TROLL:
case SP_MINOTAUR:
case SP_DEMONSPAWN:
case SP_GHOUL:
case SP_VAMPIRE:
return (CC_UNRESTRICTED);
default:
if (player_genus(GENPC_DRACONIAN))
return (CC_UNRESTRICTED);
return (CC_RESTRICTED);
}
default:
return (CC_RESTRICTED);
}
}
bool is_valid_job(job_type job)
{
return (job >= 0 && job < NUM_JOBS);
}
if (player_size(PSIZE_BODY) < SIZE_MEDIUM
&& !check_weapon_wieldable_size(*weapon, player_size(PSIZE_BODY)))
if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM
&& !check_weapon_wieldable_size(*weapon, you.body_size(PSIZE_BODY)))