#include "arguments.h" #include #include #include #include #include #include "constants.h" #include "input/file_input.h" #include "output/file_output.h" #include "input/console_input.h" #include "output/console_output.h" #include "input/curses_input.h" #include "output/curses_output.h" #include "rng.h" feature proc_args(int argc, char **argv, std::unique_ptr &curse, std::unique_ptr &in, std::unique_ptr &out, std::unique_ptr &rng, std::ifstream &data) { feature result = 0; std::string str; std::string fn_fin; std::string fn_fout; std::string fn_lout; std::string fn_save; std::string seed; for (int i = 1; i < argc; ++i) { str = argv[i]; if (str == "-n") { if (result & (FEATURE_IN_FILE | FEATURE_OUT_FILE)) return FEATURE_CONFLICT | i; result |= FEATURE_NCURSES; } else if (str == "-r") { if (result & FEATURE_READ_MAP) return FEATURE_CONFLICT | i; result |= FEATURE_RAND_MAP; } else if (str == "-c") { result |= FEATURE_ENEMIES_CHASE; } else if (str == "-d") { result |= FEATURE_DOORS; } else if (str == "-i") { result |= FEATURE_INVENTORY | FEATURE_WALK_OVER; } else if (str == "-t") { result |= FEATURE_THROW | FEATURE_INVENTORY | FEATURE_WALK_OVER; } else if (str == "-R") { if (result & FEATURE_READ_MAP) return FEATURE_CONFLICT | i; result |= FEATURE_REVISIT; } else if (str == "-e") { result |= FEATURE_EXTRA_STUFF; } else if (str == "-E") { if (result & FEATURE_READ_MAP) return FEATURE_CONFLICT | i; result |= FEATURE_EXTRA_LEVELS; } else if (str == "-o") { result |= FEATURE_WALK_OVER; } else if (str == "-m") { if ((result & FEATURE_RAND_MAP) || (result & FEATURE_REVISIT) || (result & FEATURE_EXTRA_LEVELS) || (result & FEATURE_READ_MAP)) return FEATURE_CONFLICT | i; result |= FEATURE_READ_MAP; ++i; str = argv[i]; data.open(str); } else if (str == "-s") { ++i; str = argv[i]; if (!seed.empty() && seed != str) return FEATURE_CONFLICT | i; seed = str; result |= FEATURE_SEED; } else if (str == "-I") { ++i; str = argv[i]; if (!fn_fin.empty() && fn_fin != str) return FEATURE_CONFLICT | i; fn_fin = str; result |= FEATURE_IN_FILE; } else if (str == "-O") { ++i; str = argv[i]; if (!fn_fout.empty() && fn_fout != str) return FEATURE_CONFLICT | i; fn_fout = str; result |= FEATURE_OUT_FILE; } else if (str == "-h" || str == "--help") { return FEATURE_LIST_ARGS; } else if (str == "--races") { return FEATURE_LIST_RACES; } else if (str == "--enemies") { return FEATURE_LIST_ENEMIES; } else if (str == "--potions") { return FEATURE_LIST_POTIONS; } else if (str == "--commands") { return FEATURE_LIST_COMMANDS; } else { return FEATURE_PANIC | i; } } if (result & FEATURE_IN_FILE) { std::ifstream fin(fn_fin); if (!fin.good()) return FEATURE_PANIC_FILE | FEATURE_IN_FILE; in = std::make_unique(std::move(fin)); } else if (!(result & FEATURE_NCURSES)) in = std::make_unique(std::cin); if (result & FEATURE_OUT_FILE) { std::ofstream fout(fn_fout); if (!fout.good()) return FEATURE_PANIC_FILE | FEATURE_OUT_FILE; out = std::make_unique(std::move(fout)); } else if (!(result & FEATURE_NCURSES)) out = std::make_unique(std::cout); if (result & FEATURE_NCURSES) { curse = std::make_unique(); in = std::make_unique(curse.get()); out = std::make_unique(curse.get()); } if (result & FEATURE_SEED) { std::istringstream iss {seed}; unsigned int tmp; if (!(iss >> tmp)) return FEATURE_PANIC_SEED; rng = std::make_unique(tmp); } else { rng = std::make_unique(); } return result; } // IMPORTANT: This is meant for already panicking void panic_args(feature panic) { using namespace std; if (panic & FEATURE_PANIC) cerr << "Invalid argument No. " << (panic ^ FEATURE_PANIC) << "!" << endl; else if (panic & FEATURE_CONFLICT) cerr << "Argument No. " << (panic ^ FEATURE_CONFLICT) << " conflicts with a previous argument!" << endl; else if (panic & FEATURE_PANIC_FILE) { switch (panic ^ FEATURE_PANIC_FILE) { case FEATURE_IN_FILE: cerr << "Cannot open specified input file!" << endl; break; case FEATURE_OUT_FILE: cerr << "Cannot open specified output file!" << endl; break; default: cerr << "Something must have went really, really, wrong..." << endl; break; } } else if (panic & FEATURE_PANIC_SEED) { cerr << "Invalid seed!" << endl; } else cerr << "Something must have went really, really, wrong..." << endl; } const char *ARGS_LIST = "\ -n : Use ncurses for I/O\n\ -r : Randomly generate maps. CANNOT BE USED WITH -m.\n\ -c : Enemies chase the player (CAUTION: THEY CAN REALLY CHASE!!!)\n\ -d : Enemies can go through doors (CAUTION: DO NOT ENABLE WITH CHASING!)\n\ -i : Enable inventory (player can pick up potions, will turn on -o)\n\ -t : Enable throw (will turn on -i)\n\ -R : Enable revisiting levels. CANNOT BE USED WITH -m.\n\ -e : Enable extra potions and races\n\ -E : Enable extra levels. CANNOT BE USED WITH -m.\n\ -o : Allows characters to go over gold and potions\n\ -m [file] : Reads map data from file. CANNOT BE USED WITH -r or -R or -E.\n\ -s [seed] : Sets initial seed to seed\n\ -I [file] : Reads commands from file. CANNOT BE USED WITH -n.\n\ -O [file] : Outputs to file. CANNOT BE USED WITH -n.\n\ -h/--help : Displays options list (doesn't start a game)\n\ --races : Displays playable characters list\n\ --enemies : Displays enemies list\n\ --potions : Displays potions list\n\ --commands : Displays available commands\n"; const char *COMMANDS_LIST = "\ Text-based commands:\n\ Basic commands:\n\ q : quits game (in inventory, close inventory)\n\ r : restarts a new game\n\ yes : confirms (in main menu) or use (in inventory)\n\ In-menu commands:\n\ s : starts the game as a shade\n\ d : starts the game as a drow\n\ v : starts the game as a vampire\n\ g : starts the game as a goblin\n\ t : starts the game as a troll\n\ Directional commands:\n\ no : north\n\ so : south\n\ ea : east\n\ we : west\n\ ne : northeast\n\ nw : northwest\n\ se : southeast\n\ sw : southwest\n\ In-game commands:\n\ f : toggles whether or not enemies stop moving\n\ u [direction] : try to use the potion indicated by direction\n\ a [direction] : try to attack the enemy indicated by direction\n\ i : toggles inventory on and off\n\ T [direction] : (in inventory) throw the selected potion towards direction\n\n\ ncurses-based commands:\n\ Basic commands:\n\ q : quits game (in inventory, close inventory)\n\ r : restarts a new game\n\ e : confirms (in main menu) or use (in inventory)\n\ Directional commands:\n\ k : north\n\ j : south\n\ l : east\n\ h : west\n\ u : northeast\n\ y : northwest\n\ n : southeast\n\ b : southwest\n\ In-game commands:\n\ f : toggles whether or not enemies stop moving\n\ u [direction] : try to use the potion indicated by direction\n\ [direction] : also tries to attack in the indicated direction\n\ i : toggles inventory on and off\n\ t [direction] : (in inventory) throw the selected potion towards direction\n\ > : go down the stairs\n\ < : go up the stairs\n"; const char *RACES_LIST = "\ - Shade (125 HP, 25 Atk, 25 Def, 1/1 Hit Rate):\n\ The most basic race.\n\n\ - Drow (150 HP, 25 Atk, 15 Def, 1/1 Hit Rate):\n\ All potions have their effect magnified by 1.5.\n\n\ - Vampire (50 HP, 25 Atk, 25 Def, 1/1 Hit Rate):\n\ Gains 5 HP on every successful attack;\n\ Has no maximum HP.\n\n\ - Troll (120 HP, 25 Atk, 15 Def, 1/1 Hit Rate):\n\ Gains 5 HP every turn.\n\n\ - Goblin (110 HP, 15 Atk, 20 Def, 1/1 Hit Rate):\n\ Gains an additional 5 gold from every slain enemy.\n\n\ - T-800 (800 HP, 40 Atk, 50 Def, 2/3 Hit Rate):\n\ All potions will give it rusty joints.\n\n\ - Mr. Goose (130 HP, 25 Atk, 20 Def, never misses):\n\ All potions are known at the beginning of the game;\n\n\ - Monk (125 HP (starts with 100 HP), 70 Atk, 0 Def, 1/1 Hit Rate):\n\ Gains 2 HP every turn.\n\n\ - Tavern Brawler (120 HP, 20 Atk, 15 Def, 3/4 Hit Rate):\n\ Has a 1/2 chance of attacking twice and 1/2 change of attacking three times.\n\n\ - Assassin (100 HP, 30 Atk, 10 Def, 1/1 Hit Rate):\n\ Upon a successful hit, has a 1/10 chance of assassinating the target.\n"; const char *ENEMIES_LIST = "\ - Human 'H' (140 HP, 20 Atk, 20 Def, 1/2 Hit Rate):\n\ Upon death, drops 2 normal piles of gold.\n\n\ - Dwarf 'W' (100 HP, 20 Atk, 30 Def, 1/2 Hit Rate):\n\ Vampires are allergic to them.\n\n\ - Elf 'E' (140 HP, 30 Atk, 10 Def, 1/2 Hit Rate):\n\ Gets two attacks against every race except drow.\n\n\ - Orc 'O' (180 HP, 30 Atk, 25 Def, 1/2 Hit Rate):\n\ Does 50% more damage to goblins.\n\n\ - Merchant 'M' (30 HP, 70 Atk, 5 Def, 1/2 Hit Rate):\n\ Starts out neutral to all characters, can be angered by PC.\n\n\ - Dragon 'D' (150 HP, 20 Atk, 20 Def, 1/2 Hit Rate):\n\ Always guards a treasure hoard.\n\n\ - Halfling 'L' (100 HP, 15 Atk, 20 Def, 1/2 Hit Rate):\n\ Has an additional 50% chance to dodge PC's attack.\n\n\ - Viking 'V' (150 HP, 30 Atk, 25 Def, 1/3 Hit Rate):\n\ Gets two attacks against every race.\n\n\ - Swordsman 'S' (100 HP, 25 Atk, 15 Def, 1/1 Hit Rate):\n\ Attacks with finess.\n\n\ - Leprechaun 'l' (80 HP, 10 Atk, 15 Def, 1/2 Hit Rate):\n\ Steals 3 pieces of gold from PC with every successful attack;\n\ If PC doesn't have enough gold, hit instead with a strong attack of fixed Atk;\n\ Upon death, drops all stolen gold plus 5 extra.\n\n\ - Witch 'Z' (100 HP, 20 Atk, 15 Def, 1/2 Hit Rate):\n\ Upon a successful hit, has a 1/5 chance of applying a random potion onto PC (starts to take effect the next turn).\n\n\ - Hacker 'h' (90 HP, 15 Atk, 30 Def, 1/2 Hit Rate):\n\ He has been in grinding in MC for too long.\n\n\ - Baby Dragon 'B' (140 HP, 20 Atk, 40 Def, 1/3 Hit Rate):\n\ Not fully grown, can move;\n\ Immune to all potions.\n"; const char *POTIONS_LIST = "\ - Restore Health (RH):\n\ Instantly restore 10 HP.\n\n\ - Boost Atk (BA):\n\ Increase ATK by 5 until exiting the level.\n\n\ - Boost Def (BD):\n\ Increase DEF by 5 until exiting the level.\n\n\ - Poison Health (PH):\n\ Instantly lose 10 HP.\n\n\ - Wound Atk (WA):\n\ Decrease ATK by 5 until exiting the level.\n\n\ - Wound Def (BD):\n\ Decrease DEF by 5 until exiting the level.\n\n\ - Continuous Restoration (CR):\n\ Restores 3 HP every turn for 5 turns.\n\n\ - Savage Strike (SS):\n\ Gets 1.25x basic ATK multiplier;\n\ Gets 0.8x basic hit rate multiplier;\n\ Lasts 20 turns.\n\n\ - Echoing Resilience (ER):\n\ Restores 7 HP every turn;\n\ Decrease basic ATK by 10;\n\ Decrease basic DEF by 10;\n\ Lasts 20 turns.\n\n\ - Tempest Tantrum (TT):\n\ Instantly loses 25% of current HP;\n\ Gets 3x final ATK multiplier;\n\ Gets 0.5x final DEF multiplier;\n\ Lasts 12 turns.\n\n\ - Bezerk Brew (BB):\n\ Gets 2x basic ATK multiplier;\n\ Gets 0.5x basic DEF multiplier;\n\ Lasts 15 turns.\n\n\ - Borrow Life (BL):\n\ Gains 50 HP upon use (can go over racial limit)\n\ Loses 55 HP after 24 turns.\n\n\ - Fine Booze (FB):\n\ Restores 2 HP every turn;\n\ Gets 0.7x final hit rate multiplier;\n\ Gives tavern brawlers the ability to never miss;\n\ Lasts 12 turns.\n\n\ - Ironclad Ward (IW):\n\ Gets 0.5x final ATK multiplier;\n\ Gets 3x final DEF multiplier;\n\ Gets 0.75x final hit rate multiplier;\n\ Lasts 12 turns.\n"; void print_list(feature which) { if (which & FEATURE_LIST_ARGS) std::cout << ARGS_LIST; else if (which & FEATURE_LIST_COMMANDS) std::cout << COMMANDS_LIST; else if (which & FEATURE_LIST_ENEMIES) std::cout << ENEMIES_LIST; else if (which & FEATURE_LIST_POTIONS) std::cout << POTIONS_LIST; else if (which & FEATURE_LIST_RACES) std::cout << RACES_LIST; }