// Hyperbolic Rogue -- commandline options // Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details /** \file commandline.cpp * \brief Commandline options support */ #include "hyper.h" namespace hr { #ifdef RESOURCEDESTDIR EX string rsrcdir = RESOURCEDESTDIR; #endif #ifndef RESOURCEDESTDIR EX string rsrcdir = ""; #endif #if CAP_COMMANDLINE EX const char *scorefile = "hyperrogue.log"; EX namespace arg { EX eLand readland(const string& ss) { if(ss == "II") return laCrossroads2; if(ss == "III") return laCrossroads3; if(ss == "IV") return laCrossroads4; if(ss == "V") return laCrossroads5; for(int l=0; l, version " VER "\n"); #if !NOLICENSE printf("released under GNU General Public License version 2 and thus\n"); printf("comes with absolutely no warranty; see COPYING for details\n"); #endif #ifdef FHS static string sbuf, cbuf; if(getenv("HOME")) { sbuf = getenv("HOME"); sbuf += "/."; sbuf += scorefile; cbuf = getenv("HOME"); cbuf += "/."; cbuf += conffile; scorefile = sbuf.c_str(); conffile = cbuf.c_str(); } #endif } EX namespace arg { EX int curphase; EX vector argument; EX int pos; EX void lshift() { pos++; } EX void unshift() { pos--; } EX void shift() { lshift(); if(pos >= isize(argument)) { printf("Missing parameter\n"); exit(1); } } EX bool nomore() { return pos >= isize(argument); } EX const string& args() { return argument[pos]; } EX const char* argcs() { return args().c_str(); } EX int argi() { return atoi(argcs()); } EX unsigned arghex() { return strtoll(argcs(), NULL, 16); } EX ld argf() { try { return parseld(args()); } catch(hr_parse_exception& ex) { println(hlog, "error parsing commandline parameters: ", ex.s); exit(1); } } EX bool argis(const string& s) { if(args()[0] == '-' && args()[1] == '-') return args().substr(1) == s; return args() == s; } EX void shift_arg_formula(ld& x, const reaction_t& r IS(reaction_t())) { shift(); ld old = x; x = argf(); #if CAP_ANIMATIONS anims::animate_parameter(x, args(), r); #endif if(old != x && r) r(); } #if HDR // an useful macro #define PHASE(x) { if(arg::curphase > x) arg::phaseerror(x); else if(arg::curphase < x) return 2; } #define PHASEFROM(x) { if(arg::curphase < x) return 2; } #define TOGGLE(x, param, act) \ else if(args()[0] == '-' && args()[1] == x && !args()[2]) { PHASEFROM(2); showstartmenu = false; act; } \ else if(args()[0] == '-' && args()[1] == x && args()[2] == '1') { PHASEFROM(2); showstartmenu = false; if(!param) act; } \ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); showstartmenu = false; if(param) act; } #endif EX void cheat() { autocheat = true; cheater++; timerghost = false; } EX void init(int argc, char **argv) { for(int i=0; i= '0' && c <= '9') { debugflags &= DF_TIME; if(c >= '1') debugflags |= DF_INIT | DF_WARN | DF_MSG | DF_ERROR; if(c >= '2') debugflags |= DF_GEOM | DF_GP | DF_LOG | DF_FIELD | DF_POLY; if(c >= '3') debugflags |= DF_TURN | DF_STEAM; if(c >= '4') debugflags |= DF_GRAPH | DF_MEMORY; } else if(c == '+') { if(debugfile) fclose(debugfile); shift(); println(hlog, "writing to ", argcs()); debugfile = fopen(argcs(), "at"); } else if(c == '@') { if(debugfile) fclose(debugfile); shift(); println(hlog, "writing to ", argcs()); debugfile = fopen(argcs(), "wt"); } } } else if(argis("-run")) { PHASE(3); start_game(); mainloop(); quitmainloop = false; } else if(argis("-msg")) { shift(); addMessage(args()); printf("%s\n", args().c_str()); } else if(argis("-msg0")) { clearMessages(); } #if CAP_TOUR else if(argis("-tour")) { showstartmenu = false; PHASEFROM(2); start_game(); tour::start(); } else if(argis("-presentation")) { PHASEFROM(2); tour::texts = false; start_game(); tour::start(); } else if(argis("-print-tour")) { tour::print(); } #endif else if(argis("-draw")) { PHASE(3); start_game(); drawscreen(); } else if(argis("-rotate")) { PHASE(3); start_game(); shift(); ld a = argf(); shift(); ld b = argf(); View = View * spin(M_PI * 2 * a / b); } else if(argis("-rotate3")) { PHASE(3); start_game(); shift(); ld a = argf(); shift(); ld b = argf(); View = View * cspin(1, 2, M_PI * 2 * a / b); } else if(argis("-face-vertex")) { PHASE(3); start_game(); View = cspin(0, 2, M_PI/2) * spintox(cgi.vertices_only[0]); } else if(argis("-face-face")) { PHASE(3); start_game(); View = cspin(0, 2, M_PI/2); } else if(argis("-grotate")) { PHASE(3); start_game(); shift(); int i = argi(); shift(); int j = argi(); shift(); View = View * cspin(i, j, argf()); } else if(argis("-exit")) { PHASE(3); printf("Success.\n"); exit(0); } // graphical options else if(argis("-noscr")) { PHASE(3); popScreenAll(); showstartmenu = false; } else if(argis("-viz")) { PHASE(3); showstartmenu = false; start_game(); popScreenAll(); clearMessages(); nohud = true; mapeditor::drawplayer = false; } else if(argis("-vizhr")) { PHASE(3); showstartmenu = false; popScreenAll(); clearMessages(); } // informational else if(argis("-version") || argis("-v")) { printf("HyperRogue version " VER "\n"); exit(0); } else if(argis("-L")) { printf("Treasures:\n"); for(int i=1; i - fieldpattern: quotient by the given (must be followed by qpar)\n"); printf(" -qpar - fieldpattern: use the given prime instead of 43\n"); printf(" -cs - fieldpattern: set subpath to the given (cannot be followed by qpar)\n"); printf(" -csp - fieldpattern: find the subpath of order (cannot be followed by qpar)\n"); printf(" -S* - toggle Shmup\n"); printf(" -P n - switch Shmup number of players (n=1..7)\n"); printf(" -PM - switch the model index\n"); printf(" -H* - toggle Hardcore\n"); printf(" -T* - toggle Tactical\n"); printf(" -7* - toggle heptagonal mode\n"); printf(" -C* - toggle Chaos mode\n"); printf(" -R* - toggle Random Pattern\n"); printf(" -Y id - enable Yendor, level id\n"); printf(" -D - disable all the special game modes\n"); printf(" -L - list of features\n"); printf(" -debugf 7 - output debugging information to hyperrogue-debug.txt\n"); printf(" -debuge 7 - output debugging information to stderr\n"); printf(" -offline - don't connect to Steam (for Steam versions)\n"); printf(" -I ITEM n - start with n of ITEM (activates cheat and disables ghosts)\n"); printf(" -fix - fix the seed\n"); printf("Toggles: -o0 disables, -o1 enables, -o switches"); printf("Not all options are documented, see hyper.cpp"); exit(0); } else return 1; return 0; } EX purehookset hooks_config; EX hookset hooks_args; EX map> *added_commands; EX namespace arg { int read_added_commands() { if(!added_commands) return 1; if(added_commands->count(args())) { auto& ac = (*added_commands)[args()]; if(ac.first == 2) PHASEFROM(2); if(ac.first == 3) PHASE(3); ac.second(); return 0; } return 1; } EX int add_at(const string& s, int at, const reaction_t& r) { if(!added_commands) added_commands = new map> (); if(added_commands->count(s)) throw hr_exception("arg::add conflict"); (*added_commands)[s] = {at, r}; return 1; } EX int add1(const string& s, const reaction_t& r) { return add_at(s, 1, r); } EX int add2(const string& s, const reaction_t& r) { return add_at(s, 2, r); } EX int add3(const string& s, const reaction_t& r) { return add_at(s, 3, r); } auto ah = addHook(hooks_args, 0, readCommon) + addHook(hooks_args, 200, read_added_commands); void read(int phase) { curphase = phase; callhooks(hooks_config); while(pos < isize(argument)) { int r = callhandlers(1, hooks_args); switch (r) { case 0: lshift(); break; case 1: printf("Unknown option: %s\n", argcs()); exit(3); break; case 2: return; default: assert(false); } } } EX } #endif #if !CAP_COMMANDLINE EX namespace arg { EX int add1(const string& s, const reaction_t& r) { } EX int add2(const string& s, const reaction_t& r) { } EX int add3(const string& s, const reaction_t& r) { } EX } #endif }