357 lines
14 KiB
C++
357 lines
14 KiB
C++
#include "arguments.h"
|
|
|
|
#include <iostream>
|
|
#include <utility>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#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<cursor> &curse,
|
|
std::unique_ptr<input> &in,
|
|
std::unique_ptr<output> &out,
|
|
std::unique_ptr<RNG> &rng) {
|
|
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") {
|
|
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") {
|
|
result |= FEATURE_REVISIT;
|
|
} else if (str == "-e") {
|
|
result |= FEATURE_EXTRA_STUFF;
|
|
} else if (str == "-E") {
|
|
result |= FEATURE_EXTRA_LEVELS;
|
|
} else if (str == "-o") {
|
|
result |= FEATURE_WALK_OVER;
|
|
} 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<file_input>(std::move(fin));
|
|
} else if (!(result & FEATURE_NCURSES))
|
|
in = std::make_unique<console_input>(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<file_output>(std::move(fout));
|
|
} else if (!(result & FEATURE_NCURSES))
|
|
out = std::make_unique<console_output>(std::cout);
|
|
|
|
if (result & FEATURE_NCURSES) {
|
|
curse = std::make_unique<cursor>();
|
|
in = std::make_unique<curses_input>(curse.get());
|
|
out = std::make_unique<curses_output>(curse.get());
|
|
}
|
|
|
|
if (result & FEATURE_SEED) {
|
|
std::istringstream iss {seed};
|
|
unsigned int tmp;
|
|
|
|
if (!(iss >> tmp))
|
|
return FEATURE_PANIC_SEED;
|
|
|
|
rng = std::make_unique<RNG>(tmp);
|
|
} else {
|
|
rng = std::make_unique<RNG>();
|
|
}
|
|
|
|
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\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\n\
|
|
-e : Enable extra potions and races\n\
|
|
-E : Enable extra levels\n\
|
|
-o : Allows characters to go over gold and potions\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 know 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.\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 5 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 deduct 5 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;
|
|
}
|