Also move species<->string translation from player.cc to species.cc.
SNH6UWOYVWP4A6B4NC6YZ6KRYPYCGGNYCW5TILTALPH552H2EUFQC ZIR3QTZNQ4JHRPSCFXKBY6Q7F4S4QLMYH26HTECBBTAZ7Y62GW2AC Y2FUMSP563WQWVM66N46HHBGAQ6TD5DV3K3CZQ64DRAFPVLWYCAQC JTXU5QU5KSRO2OPW7D7PXHSR4WHZDXYHDCJSFAEAR6RDMIVWNP5QC MQBPIR2ALV2KSE3YLXPBFEGYJBXFOTMGCRYBOEVNPHYGZD5OHAZQC UIIGQWA5DET6T62DCYRAFTQF35NZJ2TVULR3SR2VXV2AMKGOGHMAC JDM5R3HYGXKQKZWY35QZ2KOB24TFZ3FW2PCNXCRCMWG72AZC5ZXQC UJHVY3MHU23VJMYKIXCDSAIXF6HH6MWKT5H2KHSJTHJVU4DYWTFAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC ESWIM76FGJL4QFLSHU6AC4D74PT7OPLQ7ZCJYWLZS5UCBAJDXYHAC Z6XF4AIERIW4U4AR3HU2ILYFZ54IK4K4ORQ6JKCEWRO5LZODWDDAC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC 2YL37AGHLFOMIF3GCTVQGGV2RNNWETWM6ZMUHO3QEWDVBFFSFAKQC QG7MKYZECIRDJJZKVRFI6XTCH42GTKA55BFIWPJBQZ27CZVLUJDQC M5ZDZJBTOJ7SWQPZZQPC24JYZKP26MWSRDHXBWQE2MPPL6WCXOIQC RISMOCQM6BKK4XSIRKYLOBB2UPDYJNDAL6OGIIR5GGNZQAK5YSZAC ZBPZZ5A7AB2VFZKQ2UJXVDGUK22OCZJCEN2RWTGDGK3VXFCCDKVAC QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC N6SBZYHPKCHUZ5UQJLYYIEK62TTEV7YWZXHPTPNVHWPHR6XZRF4AC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC EO4FXWNFJRHPOSDHWH2Y6QNUP7KB5ANLX43GA3TJLXR3QOOJZ7VQC AVEOSLDREJHWFZE6ULAWGQPDT24YX4OAOGL7YAUCFVRGHCS22UCAC VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC VJZ4D26E4L4E22SO6UYB44DNUTLG72LA4GTAEZ2DKKEMAICHOXBQC RPI3C7RPSAS4E76BMEDHEPOFX2UU2LUEIQNSRDO65HJ7CRPKNDSQC S6ADNAPM545WP3FRHCU6UWKX5VEMY5TPSIZYSZ3XE76VCBTVIN5QC 6O5667Y65C5GTP4V3NBKWUN22IRGCAXEELJ6MCANMYPBOKDUO75QC WN3ZHNL4T7QMQC6JF5DJR6NHLZVOGQVO4OJNEKEM5FZKQ7AVOP4AC UKYGZDI6PYZPXDACCQGVPHANUP5ADCSNROOZIE7LYIZQWSNFHJZAC M5FC232XYPYMLL4WYYD4WHCDS36NZD762CFHRHGNK7TNXGZGZNZAC 33MBISZXMRGZMQ37PVINHKNWAXHYPHURMRG6ST7O2SKIRGGBHI2AC RKBFYX6A3ORSXOVFPBGZFHL25AMX754YAT6M23FNGYXBXZ4DSFAAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC CPUDHKEC3NYEKINBNTRDSKH4NLRQHDLGX432SIYLK5YASCE4O3RQC JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC BTO5WE4OEK64DZQVNYLOESM74KKQNE7KSNMQVF5UDB26OBKP7ORQC BVVC3O42KD4PA2QTD2NUBHPDZXYE2SFPSCDMW4F5FNA4QDTU7F4AC QEEJFAETO6B2J4IWDIDCJ5UNIFNNHHG22IWF2CUJRTJJBNE47CWQC C2PRXJYHDRF2642VDAUY76HJKCPQFGWDI6AM3SMCMYCHGWYDQXQQC WMFU65IAJ3LX2YSFXXRS7ZFNDCZYQC3ZQ3QDHHK3DU3UMLJMAP4QC YVXBG7RWH64BDT6WPAPIEINOXRXLF2ROXK6HZVKBQHK2TOBAFK5QC FS732HH3GBQCSQRKU5ZYBYVLDBGOAGBWDNKHQV5HETPT634CFLDAC SOCA7SXH3OXTPFBVXHWXPLMIYXCQQBDT72KVCDM4445PIKTU3GZQC KKNUX66ORZWWQH4ARKCHPHNDOYCI65STE3A27LKA3FWUKIX7MAXQC PNRMCHHEBCAUD2XBSSH6JOEQ6A6CFEZBCIX436DVD26DA52OCYTQC DE2BXPJDLWN7F3LAYKUSWI5CFEYZMV2ZN4K2Y356NWIX4AIGD73QC VDMADGWYGYZJWAEWU3WE7UCPVDS2O6HOHCXLOML64U5UCH4FER3AC LCDAVMTTCXQW6AOXG4IHXGRGVNMA47ZKHXW3NDYK2YFJFBMCFFQAC BTDIRPAGSX5DWEEV62VGTYALWM6G5LKFKHT7HYJXVH7XBA4BPHLQC LABXKXWWQY2V4FUDLGVTDYHXINAP6KRHZDHBQ2FE22FFOEIZPL6QC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC WNC5SY6P2PBCU62Q2DB5J2M4HPDS5EJY76ZEPHRGGCLJ4BSLBSSQC LPTP6ZL7U4OVXLZ56TJKJ6HENDHE7ITFMFBXC5BKEBVXEGXPW44AC YATODO2EN3AW7IXW5PL25HHK34YHF6Y32QBMOUZXEATZZ4YQQWZQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC FMBJCM5LJKCG326YRJGOOJU6QNWONXAHK2AB4CP4SAOHKJ5CORXQC EJKHYV2Z6UPRVYUAL4WRW33GBNHYBFPMPA57HMBX2LQKXHIUO5VQC #ifndef SPECIES_H#define SPECIES_H// from newgame.ccspecies_type get_species(const int index);species_type random_draconian_player_species();int ng_num_species();int get_species_by_abbrev(const char *abbrev);const char *get_species_abbrev(int which_species);int get_species_index_by_abbrev(const char *abbrev);int get_species_index_by_name(const char *name);// from player.ccstd::string species_name( species_type speci, int level, bool genus = false,bool adj = false );int str_to_species(const std::string &species);#endif
#include "AppHdr.h"#include "species.h"#include "stuff.h"// 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. (jpeg)//// These are 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_DEEP_ELF, SP_SLUDGE_ELF,SP_MOUNTAIN_DWARF, SP_HALFLING,SP_HILL_ORC, SP_KOBOLD,SP_MUMMY, SP_NAGA,SP_OGRE, SP_TROLL,SP_RED_DRACONIAN, SP_CENTAUR,SP_DEMIGOD, SP_SPRIGGAN,SP_MINOTAUR, SP_DEMONSPAWN,SP_GHOUL, SP_KENKU,SP_MERFOLK, SP_VAMPIRE,SP_DEEP_DWARF};// Fantasy staples and humanoid creatures come first, then diminutive 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 looksSP_HUMAN, SP_HIGH_ELF,SP_DEEP_ELF, SP_SLUDGE_ELF,SP_MOUNTAIN_DWARF, SP_DEEP_DWARF,SP_HILL_ORC, SP_MERFOLK,// small speciesSP_HALFLING, SP_KOBOLD,SP_SPRIGGAN,// significantly different body type from humanSP_NAGA, SP_CENTAUR,SP_OGRE, SP_TROLL,SP_MINOTAUR, SP_KENKU,SP_RED_DRACONIAN,// celestial speciesSP_DEMIGOD, SP_DEMONSPAWN,// undead speciesSP_MUMMY, SP_GHOUL,SP_VAMPIRE};species_type random_draconian_player_species(){const int num_drac = SP_PALE_DRACONIAN - SP_RED_DRACONIAN + 1;return static_cast<species_type>(SP_RED_DRACONIAN + random2(num_drac));}species_type get_species(const int index){if (index < 0 || (unsigned int) index >= ARRAYSZ(old_species_order))return (SP_UNKNOWN);return (Options.use_old_selection_order ? old_species_order[index]: new_species_order[index]);}static const char * Species_Abbrev_List[NUM_SPECIES] ={ "XX", "Hu", "HE", "DE", "SE", "MD", "Ha","HO", "Ko", "Mu", "Na", "Og", "Tr",// the draconians"Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr","Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "DD",// placeholders"El", "HD", "OM", "GE", "Gn" };int get_species_index_by_abbrev(const char *abbrev){COMPILE_CHECK(ARRAYSZ(Species_Abbrev_List) == NUM_SPECIES, c1);for (unsigned i = 0; i < ARRAYSZ(old_species_order); i++){const int sp = (Options.use_old_selection_order ? old_species_order[i]: new_species_order[i]);if (tolower( abbrev[0] ) == tolower( Species_Abbrev_List[sp][0] )&& tolower( abbrev[1] ) == tolower( Species_Abbrev_List[sp][1] )){return (i);}}return (-1);}int get_species_index_by_name( const char *name ){unsigned int i;int sp = -1;std::string::size_type pos = std::string::npos;char lowered_buff[80];strncpy(lowered_buff, name, sizeof(lowered_buff));strlwr(lowered_buff);for (i = 0; i < ARRAYSZ(old_species_order); i++){const species_type real_sp= (Options.use_old_selection_order ? old_species_order[i]: new_species_order[i]);const std::string lowered_species =lowercase_string(species_name(real_sp,1));pos = lowered_species.find( lowered_buff );if (pos != std::string::npos){sp = i;if (pos == 0) // prefix takes preferencebreak;}}return (sp);}const char *get_species_abbrev( int which_species ){ASSERT( which_species > 0 && which_species < NUM_SPECIES );return (Species_Abbrev_List[ which_species ]);}// Needed for debug.cc and hiscores.cc.int get_species_by_abbrev( const char *abbrev ){int i;COMPILE_CHECK(ARRAYSZ(Species_Abbrev_List) == NUM_SPECIES, c1);for (i = SP_HUMAN; i < NUM_SPECIES; i++){if (tolower( abbrev[0] ) == tolower( Species_Abbrev_List[i][0] )&& tolower( abbrev[1] ) == tolower( Species_Abbrev_List[i][1] )){break;}}return ((i < NUM_SPECIES) ? i : -1);}int ng_num_species(){// The list musn't be longer than the number of actual species.COMPILE_CHECK(ARRAYSZ(old_species_order) <= NUM_SPECIES, c1);// Check whether the two lists have the same size.COMPILE_CHECK(ARRAYSZ(old_species_order) == ARRAYSZ(new_species_order), c2);return (ARRAYSZ(old_species_order));}// Does a case-sensitive lookup of the species name supplied.int str_to_species(const std::string &species){if (species.empty())return SP_HUMAN;// first look for full name (e.g. Green Draconian)for (int i = SP_HUMAN; i < NUM_SPECIES; ++i){if (species == species_name(static_cast<species_type>(i), 10))return (i);}// nothing found, try again with plain namefor (int i = SP_HUMAN; i < NUM_SPECIES; ++i){if (species == species_name(static_cast<species_type>(i), 1))return (i);}return (SP_HUMAN);}std::string species_name(species_type speci, int level, bool genus, bool adj)// defaults: false false{std::string res;if (player_genus( GENPC_DRACONIAN, speci )){if (adj || genus) // adj doesn't care about exact speciesres = "Draconian";else{if (level < 7)res = "Draconian";else{switch (speci){case SP_RED_DRACONIAN: res = "Red Draconian"; break;case SP_WHITE_DRACONIAN: res = "White Draconian"; break;case SP_GREEN_DRACONIAN: res = "Green Draconian"; break;case SP_YELLOW_DRACONIAN: res = "Yellow Draconian"; break;case SP_GREY_DRACONIAN: res = "Grey Draconian"; break;case SP_BLACK_DRACONIAN: res = "Black Draconian"; break;case SP_PURPLE_DRACONIAN: res = "Purple Draconian"; break;case SP_MOTTLED_DRACONIAN: res = "Mottled Draconian"; break;case SP_PALE_DRACONIAN: res = "Pale Draconian"; break;case SP_BASE_DRACONIAN:default:res = "Draconian";break;}}}}else if (player_genus( GENPC_ELVEN, speci )){if (adj) // doesn't care about species/genusres = "Elven";else if (genus)res = "Elf";else{switch (speci){case SP_HIGH_ELF: res = "High Elf"; break;case SP_DEEP_ELF: res = "Deep Elf"; break;case SP_SLUDGE_ELF: res = "Sludge Elf"; break;default: res = "Elf"; break;}}}else if (player_genus(GENPC_DWARVEN, speci)){if (adj) // doesn't care about species/genusres = "Dwarven";else if (genus)res = "Dwarf";else{switch (speci){case SP_MOUNTAIN_DWARF: res = "Mountain Dwarf"; break;case SP_DEEP_DWARF: res = "Deep Dwarf"; break;default: res = "Dwarf"; break;}}}else{switch (speci){case SP_HUMAN: res = "Human"; break;case SP_HALFLING: res = "Halfling"; break;case SP_KOBOLD: res = "Kobold"; break;case SP_MUMMY: res = "Mummy"; break;case SP_NAGA: res = "Naga"; break;case SP_CENTAUR: res = "Centaur"; break;case SP_SPRIGGAN: res = "Spriggan"; break;case SP_MINOTAUR: res = "Minotaur"; break;case SP_KENKU: res = "Kenku"; break;case SP_HILL_ORC:res = (adj ? "Orcish" : genus ? "Orc" : "Hill Orc");break;case SP_OGRE: res = (adj ? "Ogreish" : "Ogre"); break;case SP_TROLL: res = (adj ? "Trollish" : "Troll"); break;case SP_DEMIGOD: res = (adj ? "Divine" : "Demigod"); break;case SP_DEMONSPAWN: res = (adj ? "Demonic" : "Demonspawn"); break;case SP_GHOUL: res = (adj ? "Ghoulish" : "Ghoul"); break;case SP_MERFOLK: res = (adj ? "Merfolkian" : "Merfolk"); break;case SP_VAMPIRE: res = (adj ? "Vampiric" : "Vampire"); break;default: res = (adj ? "Yakish" : "Yak"); break;}}return res;}
* called from: acr - chardump - describe - newgame - view* *********************************************************************** */std::string species_name( species_type speci, int level, bool genus = false,bool adj = false );int str_to_species(const std::string &species);/* ***********************************************************************
// Does a case-sensitive lookup of the species name supplied.int str_to_species(const std::string &species){if (species.empty())return SP_HUMAN;// first look for full name (e.g. Green Draconian)for (int i = SP_HUMAN; i < NUM_SPECIES; ++i){if (species == species_name(static_cast<species_type>(i), 10))return (i);}// nothing found, try again with plain namefor (int i = SP_HUMAN; i < NUM_SPECIES; ++i){if (species == species_name(static_cast<species_type>(i), 1))return (i);}return (SP_HUMAN);}std::string species_name(species_type speci, int level, bool genus, bool adj)// defaults: false false{std::string res;if (player_genus( GENPC_DRACONIAN, speci )){if (adj || genus) // adj doesn't care about exact speciesres = "Draconian";else{if (level < 7)res = "Draconian";else{switch (speci){case SP_RED_DRACONIAN: res = "Red Draconian"; break;case SP_WHITE_DRACONIAN: res = "White Draconian"; break;case SP_GREEN_DRACONIAN: res = "Green Draconian"; break;case SP_YELLOW_DRACONIAN: res = "Yellow Draconian"; break;case SP_GREY_DRACONIAN: res = "Grey Draconian"; break;case SP_BLACK_DRACONIAN: res = "Black Draconian"; break;case SP_PURPLE_DRACONIAN: res = "Purple Draconian"; break;case SP_MOTTLED_DRACONIAN: res = "Mottled Draconian"; break;case SP_PALE_DRACONIAN: res = "Pale Draconian"; break;
case SP_BASE_DRACONIAN:default:res = "Draconian";break;}}}}else if (player_genus( GENPC_ELVEN, speci )){if (adj) // doesn't care about species/genusres = "Elven";else if (genus)res = "Elf";else{switch (speci){case SP_HIGH_ELF: res = "High Elf"; break;case SP_DEEP_ELF: res = "Deep Elf"; break;case SP_SLUDGE_ELF: res = "Sludge Elf"; break;default: res = "Elf"; break;}}}else if (player_genus(GENPC_DWARVEN, speci)){if (adj) // doesn't care about species/genusres = "Dwarven";else if (genus)res = "Dwarf";else{switch (speci){case SP_MOUNTAIN_DWARF: res = "Mountain Dwarf"; break;case SP_DEEP_DWARF: res = "Deep Dwarf"; break;default: res = "Dwarf"; break;}}}else{switch (speci){case SP_HUMAN: res = "Human"; break;case SP_HALFLING: res = "Halfling"; break;case SP_KOBOLD: res = "Kobold"; break;case SP_MUMMY: res = "Mummy"; break;case SP_NAGA: res = "Naga"; break;case SP_CENTAUR: res = "Centaur"; break;case SP_SPRIGGAN: res = "Spriggan"; break;case SP_MINOTAUR: res = "Minotaur"; break;case SP_KENKU: res = "Kenku"; break;case SP_HILL_ORC:res = (adj ? "Orcish" : genus ? "Orc" : "Hill Orc");break;case SP_OGRE: res = (adj ? "Ogreish" : "Ogre"); break;case SP_TROLL: res = (adj ? "Trollish" : "Troll"); break;case SP_DEMIGOD: res = (adj ? "Divine" : "Demigod"); break;case SP_DEMONSPAWN: res = (adj ? "Demonic" : "Demonspawn"); break;case SP_GHOUL: res = (adj ? "Ghoulish" : "Ghoul"); break;case SP_MERFOLK: res = (adj ? "Merfolkian" : "Merfolk"); break;case SP_VAMPIRE: res = (adj ? "Vampiric" : "Vampire"); break;default: res = (adj ? "Yakish" : "Yak"); break;}}return res;}
/* ************************************************************************ called from: initfile* *********************************************************************** */int get_species_index_by_abbrev(const char *abbrev);int get_species_index_by_name(const char *name);const char *get_species_abbrev(int which_species);
int get_class_index_by_abbrev(const char *abbrev);int get_class_index_by_name(const char *name);const char *get_class_abbrev(int which_job);const char *get_class_name(int which_job);/* ************************************************************************ called from: debug and hiscores* *********************************************************************** */int get_species_by_abbrev( const char *abbrev );int get_species_by_name( const char *name );int get_class_by_abbrev( const char *abbrev );int get_class_by_name( const char *name );
// 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. (jpeg)//// These are 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_DEEP_ELF, SP_SLUDGE_ELF,SP_MOUNTAIN_DWARF, SP_HALFLING,SP_HILL_ORC, SP_KOBOLD,SP_MUMMY, SP_NAGA,SP_OGRE, SP_TROLL,SP_RED_DRACONIAN, SP_CENTAUR,SP_DEMIGOD, SP_SPRIGGAN,SP_MINOTAUR, SP_DEMONSPAWN,SP_GHOUL, SP_KENKU,SP_MERFOLK, SP_VAMPIRE,SP_DEEP_DWARF};// Fantasy staples and humanoid creatures come first, then diminutive 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 looksSP_HUMAN, SP_HIGH_ELF,SP_DEEP_ELF, SP_SLUDGE_ELF,SP_MOUNTAIN_DWARF, SP_DEEP_DWARF,SP_HILL_ORC, SP_MERFOLK,// small speciesSP_HALFLING, SP_KOBOLD,SP_SPRIGGAN,// significantly different body type from humanSP_NAGA, SP_CENTAUR,SP_OGRE, SP_TROLL,SP_MINOTAUR, SP_KENKU,SP_RED_DRACONIAN,// celestial speciesSP_DEMIGOD, SP_DEMONSPAWN,// undead speciesSP_MUMMY, SP_GHOUL,SP_VAMPIRE};static species_type _random_draconian_player_species(){const int num_drac = SP_PALE_DRACONIAN - SP_RED_DRACONIAN + 1;return static_cast<species_type>(SP_RED_DRACONIAN + random2(num_drac));}static species_type _get_species(const int index){if (index < 0 || (unsigned int) index >= ARRAYSZ(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,JOB_ARTIFICER};// 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[] = {// fightersJOB_FIGHTER, JOB_GLADIATOR,JOB_MONK, JOB_BERSERKER,// religious professions (incl. Berserker above)JOB_PALADIN, JOB_PRIEST,JOB_HEALER, JOB_CHAOS_KNIGHT,JOB_DEATH_KNIGHT, JOB_CRUSADER,// general and niche spellcasters (incl. Crusader above)JOB_REAVER, JOB_WARPER,JOB_WIZARD, JOB_CONJURER,JOB_ENCHANTER, JOB_SUMMONER,JOB_NECROMANCER, JOB_TRANSMUTER,JOB_FIRE_ELEMENTALIST, JOB_ICE_ELEMENTALIST,JOB_AIR_ELEMENTALIST, JOB_EARTH_ELEMENTALIST,// poison specialists and stabbersJOB_VENOM_MAGE, JOB_STALKER,JOB_THIEF, JOB_ASSASSIN,JOB_HUNTER, JOB_ARTIFICER,JOB_WANDERER};static job_type _get_class(const int index){if (index < 0 || (unsigned int) index >= ARRAYSZ(old_jobs_order))return (JOB_UNKNOWN);return (Options.use_old_selection_order? old_jobs_order[index]: new_jobs_order[index]);}static const char * Species_Abbrev_List[ NUM_SPECIES ] ={ "XX", "Hu", "HE", "DE", "SE", "MD", "Ha","HO", "Ko", "Mu", "Na", "Og", "Tr",// the draconians"Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr","Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "DD",// placeholders"El", "HD", "OM", "GE", "Gn" };int get_species_index_by_abbrev( const char *abbrev ){COMPILE_CHECK(ARRAYSZ(Species_Abbrev_List) == NUM_SPECIES, c1);for (unsigned i = 0; i < ARRAYSZ(old_species_order); i++){const int sp = (Options.use_old_selection_order ? old_species_order[i]: new_species_order[i]);if (tolower( abbrev[0] ) == tolower( Species_Abbrev_List[sp][0] )&& tolower( abbrev[1] ) == tolower( Species_Abbrev_List[sp][1] )){return (i);}}return (-1);}int get_species_index_by_name( const char *name ){unsigned int i;int sp = -1;std::string::size_type pos = std::string::npos;char lowered_buff[80];strncpy( lowered_buff, name, sizeof( lowered_buff ) );strlwr( lowered_buff );for (i = 0; i < ARRAYSZ(old_species_order); i++){const species_type real_sp= (Options.use_old_selection_order ? old_species_order[i]: new_species_order[i]);const std::string lowered_species =lowercase_string(species_name(real_sp,1));pos = lowered_species.find( lowered_buff );if (pos != std::string::npos){sp = i;if (pos == 0) // prefix takes preferencebreak;}}return (sp);}const char *get_species_abbrev( int which_species ){ASSERT( which_species > 0 && which_species < NUM_SPECIES );return (Species_Abbrev_List[ which_species ]);}// Needed for debug.cc and hiscores.cc.int get_species_by_abbrev( const char *abbrev ){int i;COMPILE_CHECK(ARRAYSZ(Species_Abbrev_List) == NUM_SPECIES, c1);for (i = SP_HUMAN; i < NUM_SPECIES; i++){if (tolower( abbrev[0] ) == tolower( Species_Abbrev_List[i][0] )&& tolower( abbrev[1] ) == tolower( Species_Abbrev_List[i][1] )){break;}}return ((i < NUM_SPECIES) ? i : -1);}static const char * Class_Abbrev_List[ NUM_JOBS ] ={ "Fi", "Wz", "Pr", "Th", "Gl", "Ne", "Pa", "As", "Be", "Hu","Cj", "En", "FE", "IE", "Su", "AE", "EE", "Cr", "DK", "VM","CK", "Tm", "He", "Re", "St", "Mo", "Wr", "Wn", "Ar" };static const char * Class_Name_List[ NUM_JOBS ] ={ "Fighter", "Wizard", "Priest", "Thief", "Gladiator", "Necromancer","Paladin", "Assassin", "Berserker", "Hunter", "Conjurer", "Enchanter","Fire Elementalist", "Ice Elementalist", "Summoner", "Air Elementalist","Earth Elementalist", "Crusader", "Death Knight", "Venom Mage","Chaos Knight", "Transmuter", "Healer", "Reaver", "Stalker","Monk", "Warper", "Wanderer", "Artificer" };int get_class_index_by_abbrev( const char *abbrev ){COMPILE_CHECK(ARRAYSZ(Class_Abbrev_List) == NUM_JOBS, c1);unsigned int job;for (unsigned int i = 0; i < ARRAYSZ(old_jobs_order); i++){job = (Options.use_old_selection_order ? old_jobs_order[i]: new_jobs_order[i]);if (tolower( abbrev[0] ) == tolower( Class_Abbrev_List[job][0] )&& tolower( abbrev[1] ) == tolower( Class_Abbrev_List[job][1] )){return i;}}return (-1);}const char *get_class_abbrev( int which_job ){ASSERT( which_job < NUM_JOBS );return (Class_Abbrev_List[ which_job ]);}int get_class_by_abbrev( const char *abbrev ){int i;for (i = 0; i < NUM_JOBS; i++){if (tolower( abbrev[0] ) == tolower( Class_Abbrev_List[i][0] )&& tolower( abbrev[1] ) == tolower( Class_Abbrev_List[i][1] )){break;}}return ((i < NUM_JOBS) ? i : -1);}int get_class_index_by_name( const char *name ){COMPILE_CHECK(ARRAYSZ(Class_Name_List) == NUM_JOBS, c1);char *ptr;char lowered_buff[80];char lowered_class[80];strncpy( lowered_buff, name, sizeof( lowered_buff ) );strlwr( lowered_buff );int cl = -1;unsigned int job;for (unsigned int i = 0; i < ARRAYSZ(old_jobs_order); i++){job = (Options.use_old_selection_order ? old_jobs_order[i]: new_jobs_order[i]);strncpy( lowered_class, Class_Name_List[job], sizeof( lowered_class ) );strlwr( lowered_class );ptr = strstr( lowered_class, lowered_buff );if (ptr != NULL){cl = i;if (ptr == lowered_class) // prefix takes preferencebreak;}}return (cl);}const char *get_class_name( int which_job ){ASSERT( which_job < NUM_JOBS );return (Class_Name_List[ which_job ]);}int get_class_by_name( const char *name ){int i;int cl = -1;
char *ptr;char lowered_buff[80];char lowered_class[80];strncpy( lowered_buff, name, sizeof( lowered_buff ) );strlwr( lowered_buff );for (i = 0; i < NUM_JOBS; i++){strncpy( lowered_class, Class_Name_List[i], sizeof( lowered_class ) );strlwr( lowered_class );ptr = strstr( lowered_class, lowered_buff );if (ptr != NULL){cl = i;if (ptr == lowered_class) // prefix takes preferencebreak;}}return (cl);}
// The list musn't be longer than the number of actual species.COMPILE_CHECK(ARRAYSZ(old_species_order) <= NUM_SPECIES, c1);// Check whether the two lists have the same size.COMPILE_CHECK(ARRAYSZ(old_species_order) == ARRAYSZ(new_species_order), c2);const int num_species = ARRAYSZ(old_species_order);
// The list musn't be longer than the number of actual classes.COMPILE_CHECK(ARRAYSZ(old_jobs_order) <= NUM_JOBS, c1);// Check whether the two lists have the same size.COMPILE_CHECK(ARRAYSZ(old_jobs_order) == ARRAYSZ(new_jobs_order), c2);const int num_classes = ARRAYSZ(old_jobs_order);
#ifndef JOBS_H#define JOBS_Hint ng_num_classes();job_type get_class(const int index);int get_class_index_by_abbrev(const char *abbrev);const char *get_class_abbrev(int which_job);int get_class_by_abbrev(const char *abbrev);int get_class_index_by_name(const char *name);const char *get_class_name(int which_job);int get_class_by_name(const char *name);#endif
#include "AppHdr.h"#include "jobs.h"// 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,JOB_ARTIFICER};// 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[] = {// fightersJOB_FIGHTER, JOB_GLADIATOR,JOB_MONK, JOB_BERSERKER,// religious professions (incl. Berserker above)JOB_PALADIN, JOB_PRIEST,JOB_HEALER, JOB_CHAOS_KNIGHT,JOB_DEATH_KNIGHT, JOB_CRUSADER,// general and niche spellcasters (incl. Crusader above)JOB_REAVER, JOB_WARPER,JOB_WIZARD, JOB_CONJURER,JOB_ENCHANTER, JOB_SUMMONER,JOB_NECROMANCER, JOB_TRANSMUTER,JOB_FIRE_ELEMENTALIST, JOB_ICE_ELEMENTALIST,JOB_AIR_ELEMENTALIST, JOB_EARTH_ELEMENTALIST,// poison specialists and stabbersJOB_VENOM_MAGE, JOB_STALKER,JOB_THIEF, JOB_ASSASSIN,JOB_HUNTER, JOB_ARTIFICER,JOB_WANDERER};job_type get_class(const int index){if (index < 0 || (unsigned int) index >= ARRAYSZ(old_jobs_order))return (JOB_UNKNOWN);return (Options.use_old_selection_order? old_jobs_order[index]: new_jobs_order[index]);}static const char * Class_Abbrev_List[ NUM_JOBS ] ={ "Fi", "Wz", "Pr", "Th", "Gl", "Ne", "Pa", "As", "Be", "Hu","Cj", "En", "FE", "IE", "Su", "AE", "EE", "Cr", "DK", "VM","CK", "Tm", "He", "Re", "St", "Mo", "Wr", "Wn", "Ar" };static const char * Class_Name_List[ NUM_JOBS ] ={ "Fighter", "Wizard", "Priest", "Thief", "Gladiator", "Necromancer","Paladin", "Assassin", "Berserker", "Hunter", "Conjurer", "Enchanter","Fire Elementalist", "Ice Elementalist", "Summoner", "Air Elementalist","Earth Elementalist", "Crusader", "Death Knight", "Venom Mage","Chaos Knight", "Transmuter", "Healer", "Reaver", "Stalker","Monk", "Warper", "Wanderer", "Artificer" };int get_class_index_by_abbrev( const char *abbrev ){COMPILE_CHECK(ARRAYSZ(Class_Abbrev_List) == NUM_JOBS, c1);unsigned int job;for (unsigned int i = 0; i < ARRAYSZ(old_jobs_order); i++){job = (Options.use_old_selection_order ? old_jobs_order[i]: new_jobs_order[i]);if (tolower( abbrev[0] ) == tolower( Class_Abbrev_List[job][0] )&& tolower( abbrev[1] ) == tolower( Class_Abbrev_List[job][1] )){return i;}}return (-1);}const char *get_class_abbrev( int which_job ){ASSERT( which_job < NUM_JOBS );return (Class_Abbrev_List[ which_job ]);}int get_class_by_abbrev( const char *abbrev ){int i;for (i = 0; i < NUM_JOBS; i++){if (tolower( abbrev[0] ) == tolower( Class_Abbrev_List[i][0] )&& tolower( abbrev[1] ) == tolower( Class_Abbrev_List[i][1] )){break;}}return ((i < NUM_JOBS) ? i : -1);}int get_class_index_by_name( const char *name ){COMPILE_CHECK(ARRAYSZ(Class_Name_List) == NUM_JOBS, c1);char *ptr;char lowered_buff[80];char lowered_class[80];strncpy( lowered_buff, name, sizeof( lowered_buff ) );strlwr( lowered_buff );int cl = -1;unsigned int job;for (unsigned int i = 0; i < ARRAYSZ(old_jobs_order); i++){job = (Options.use_old_selection_order ? old_jobs_order[i]: new_jobs_order[i]);strncpy( lowered_class, Class_Name_List[job], sizeof( lowered_class ) );strlwr( lowered_class );ptr = strstr( lowered_class, lowered_buff );if (ptr != NULL){cl = i;if (ptr == lowered_class) // prefix takes preferencebreak;}}return (cl);}const char *get_class_name( int which_job ){ASSERT( which_job < NUM_JOBS );return (Class_Name_List[ which_job ]);}int get_class_by_name( const char *name ){int i;int cl = -1;char *ptr;char lowered_buff[80];char lowered_class[80];strncpy( lowered_buff, name, sizeof( lowered_buff ) );strlwr( lowered_buff );for (i = 0; i < NUM_JOBS; i++){strncpy( lowered_class, Class_Name_List[i], sizeof( lowered_class ) );strlwr( lowered_class );ptr = strstr( lowered_class, lowered_buff );if (ptr != NULL){cl = i;if (ptr == lowered_class) // prefix takes preferencebreak;}}return (cl);}int ng_num_classes(){// The list musn't be longer than the number of actual classes.COMPILE_CHECK(ARRAYSZ(old_jobs_order) <= NUM_JOBS, c1);// Check whether the two lists have the same size.COMPILE_CHECK(ARRAYSZ(old_jobs_order) == ARRAYSZ(new_jobs_order), c2);return ARRAYSZ(old_jobs_order);}