📄 npc_console.c
字号:
#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <pwd.h>#include "gameutil.h"#include "npcEngine.h"#include "dndconst.h"#include "dndutil.h"#include "grammar.h"#include "npcHistory.h"#include "pcgen_interface.h"#include "wtstream.h"#define APPNAME "npc"#define MODE_STATBLOCK ( 0 )#define MODE_PCGEN ( 1 )static void heroicAbilities( int* scores, void* data );static void straight18s( int* scores, void* data );static void averageAbilities( int* scores, void* data );typedef struct tag_npcopts NPC_OPTS;typedef struct tag_lookup LOOKUP_TBL;struct tag_npcopts { long seed; int background; int alignment; int race; int classes[ 3 ]; int levels[ 3 ]; int score_strategy; int count; int gender; int mode; int wrap; char path[ 512 ]; char data_path[ 512 ]; NPCSTATBLOCKOPTS opts;};struct tag_lookup { char* name; int id;};static NPCABSCOREGENFUNC strategies[] = { 0, npcAbScoreStrategy_BestOf4d6, npcAbScoreStrategy_Straight3d6, heroicAbilities, averageAbilities, straight18s};#define HELP_RACES 1#define HELP_CLASSES 2#define HELP_ALIGNMENTS 3#define HELP_GENDERS 4#define HELP_STRATEGIES 5static LOOKUP_TBL help_lists[] = { { "alignments", HELP_ALIGNMENTS }, { "classes", HELP_CLASSES }, { "genders", HELP_GENDERS }, { "races", HELP_RACES }, { "strategies", HELP_STRATEGIES }, { 0, 0 }};static LOOKUP_TBL strategies_lookup[] = { { "18s", 5 }, { "3d6", 2 }, { "4d6", 1 }, { "average", 4 }, { "heroic", 3 }, { 0, 0 }};static LOOKUP_TBL levels[] = { { "any", levelANY }, { "high", levelHI }, { "low", levelLOW }, { "mid", levelMID }, { 0, 0 }};static LOOKUP_TBL genders[] = { { "any", gANY }, { "female", gFEMALE }, { "male", gMALE }, { 0, 0 }};static LOOKUP_TBL alignments[] = { { "any", alANY }, { "ce", alCHAOTIC | alEVIL }, { "cg", alCHAOTIC | alGOOD }, { "chaotic", alANY_CHAOTIC }, { "cn", alCHAOTIC | alGENEUTRAL }, { "evil", alANY_EVIL }, { "geneutral", alANY_GENEUTRAL }, { "good", alANY_GOOD }, { "lawful", alANY_LAWFUL }, { "lcneutral", alANY_LCNEUTRAL }, { "le", alLAWFUL | alEVIL }, { "lg", alLAWFUL | alGOOD }, { "ln", alLAWFUL | alGENEUTRAL }, { "ne", alLCNEUTRAL | alEVIL }, { "ng", alLCNEUTRAL | alGOOD }, { "nn", alLCNEUTRAL | alGENEUTRAL }, { 0, 0 }};static LOOKUP_TBL classtypes[] = { { "adept", npcADEPT }, { "any", classANY }, { "anynpc", classANY_NPC }, { "anypc", classANY_PC }, { "aristocrat", npcARISTOCRAT }, { "barbarian", pcBARBARIAN }, { "bard", pcBARD }, { "cleric", pcCLERIC }, { "commoner", npcCOMMONER }, { "druid", pcDRUID }, { "expert", npcEXPERT }, { "fighter", pcFIGHTER }, { "monk", pcMONK }, { "paladin", pcPALADIN }, { "ranger", pcRANGER }, { "rogue", pcROGUE }, { "sorcerer", pcSORCERER }, { "warrior", npcWARRIOR }, { "wizard", pcWIZARD }, { 0, 0 }};static LOOKUP_TBL racetypes[] = { { "aasimar", rcAASIMAR }, { "abandoned", rcCC_ABANDONED }, { "any", raceANY }, { "anycc", raceANY_CC }, { "anycore", raceANY_CORE }, { "anydmg", raceANY_DMG }, { "anymm", raceANY_MM }, { "aqelf", rcELF_AQUATIC }, { "aranea", rcARANEA }, { "asaath", rcCC_ASAATH }, { "azer", rcAZER }, { "batdevil", rcCC_BATDEVIL }, { "bgratman", rcCC_RATMAN_BROWNGORGER }, { "bugbear", rcBUGBEAR }, { "centaur", rcCENTAUR }, { "cgoblin", rcCC_COALGOBLIN }, { "charduni", rcCC_CHARDUNI }, { "cloudg", rcGIANT_CLOUD }, { "deepdwarf", rcDWARF_DEEP }, { "deephalf", rcHALFLING_DEEP }, { "derro", rcDWARF_DERRO }, { "dopple", rcDOPPLEGANGER }, { "dratman", rcCC_RATMAN_DISEASED }, { "drider", rcDRIDER }, { "drow", rcELF_DROW }, { "duergar", rcDWARF_DUERGAR }, { "dwarf", rcDWARF_HILL }, { "elf", rcELF_HIGH }, { "ettin", rcETTIN }, { "fdwarf", rcCC_DWARF_FORSAKEN }, { "felf", rcCC_ELF_FORSAKEN }, { "fireg", rcGIANT_FIRE }, { "fratman", rcCC_RATMAN_FOAMER }, { "frostg", rcGIANT_FROST }, { "frstgnome", rcGNOME_FOREST }, { "gnoll", rcGNOLL }, { "gnome", rcGNOME_ROCK }, { "goblin", rcGOBLIN }, { "grayelf", rcELF_GRAY }, { "grimlock", rcGRIMLOCK }, { "haga", rcHAG_ANNIS }, { "hagg", rcHAG_GREEN }, { "hags", rcHAG_SEA }, { "halfelf", rcHALFELF }, { "halfling", rcHALFLING_LIGHTFOOT }, { "halforc", rcHALFORC }, { "harpy", rcHARPY }, { "hillg", rcGIANT_HILL }, { "hobgob", rcHOBGOBLIN }, { "human", rcHUMAN }, { "iceghoul", rcCC_ICE_GHOUL }, { "kobold", rcKOBOLD }, { "kuotoa", rcKUOTOA }, { "lizard", rcLIZARDFOLK }, { "locathah", rcLOCATHAH }, { "mcora", rcCC_MANTICORA }, { "medusa", rcMEDUSA }, { "mindflayer", rcMINDFLAYER }, { "minotaur", rcMINOTAUR }, { "morgaunt", rcCC_MORGAUNT }, { "mtndwarf", rcDWARF_MOUNTAIN }, { "ogre", rcOGRE }, { "ogremage", rcOGREMAGE }, { "orc", rcORC }, { "proud", rcCC_PROUD }, { "pwretch", rcCC_PLAGUEWRETCH }, { "ratman", rcCC_RATMAN }, { "rwratman", rcCC_RATMAN_REDWITCH }, { "sahuagin", rcSAHUAGIN }, { "segoblin", rcCC_SPIDEREYEGOBLIN }, { "selement", rcCC_STRIFEELEMENTAL }, { "skindev", rcCC_SKINDEVIL }, { "stoneg", rcGIANT_STONE }, { "stormg", rcGIANT_STORM }, { "stroll", rcCC_STEPPETROLL }, { "svirf", rcGNOME_SVIRFNEBLIN }, { "tallflw", rcHALFLING_TALLFELLOW }, { "tiefling", rcTIEFLING }, { "tokal", rcCC_TOKALTRIBESMAN }, { "troglodyte", rcTROGLODYTE }, { "troll", rcTROLL }, { "ubantu", rcCC_UBANTUTRIBESMAN }, { "wildelf", rcELF_WILD }, { "woodelf", rcELF_WOOD }, { "yuantia", rcYUANTI_ABOMINATION }, { "yuantih", rcYUANTI_HALFBLOOD }, { "yuantip", rcYUANTI_PUREBLOOD }, { 0, 0 }};static int icomp( const void* x, const void* y ) { int ix = *(int*)x; int iy = *(int*)y; if( ix < iy ) return 1; if( ix > iy ) return -1; return 0;}static void heroicAbilities( int* scores, void* data ) { int i; npcAbScoreStrategy_BestOf4d6( scores, data ); scores[0] = 18; scores[1] = 18; for( i = 2; i < 6; i++ ) { if( scores[i] < 12 ) { scores[ i ] = 12; } }}static void straight18s( int* scores, void* data ) { int i; for( i = 0; i < 6; i++ ) { scores[ i ] = 18; }}static void averageAbilities( int* scores, void* data ) { int i; for( i = 0; i < 6; i++ ) { scores[i] = 10 + ( rand() % 2 ); }}static void strrepl( char* buf, char* srch, char* repl ) { char* p; int slen; int rlen; slen = strlen( srch ); rlen = strlen( repl ); p = strstr( buf, srch ); while( p != NULL ) { memmove( p+rlen, p+slen, strlen( p + slen ) + 1 ); strncpy( p, repl, rlen ); p = strstr( p+rlen, srch ); }}static int lookup( char* string, LOOKUP_TBL* tbl, int* found ) { int rc; int idx; int len; len = strlen( string ); *found = 1; for( idx = 0; tbl[ idx ].name != 0; idx++ ) { rc = strncasecmp( string, tbl[ idx ].name, len ); if( rc == 0 ) { return tbl[ idx ].id; } else if( rc < 0 ) { break; } } *found = 0; return -1;}#define USAGE APPNAME ", by Jamis Buck (jgb3@email.byu.edu)\n\\n\ Options:\n\ -r <race> -S <seed> -c <class> -g <gender>\n\ -l <level> -h (race|class|strategy|alignment|gender)\n\ -s <strategy> -n <count> -a <alignment> -b\n\ -o (a|c|i|b|s|k|l|f|p|S) -w (p|s) -p <path>\n\ -W <wrap-length> -d <data-path>\n\\n\ For <race>, <level>, <strategy>, <class>, and <alignment>, you only\n\ need to type part of the full name. To see what possible options exist\n\ for those values, use the -h option, followed by race, level, strategy,\n\ class, alignment, or gender. (No space, ie: -hrace, or -hgender).\n\\n\ If -b is given, background information is generated. The -W option will\n\ cause the lines to wrap at the given line length, at the first white space\n\ found. The -d option species the path to the NPC data files (for names and\n\ background files) -- it defaults to '~/.npc/'.\n\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -