// 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 EX bool delayed_start; #if CAP_COMMANDLINE EX string 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; 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 long long argll() { return atoll(argcs()); } EX int shift_argi() { shift(); return argi(); } EX const string& shift_args() { shift(); return args(); } 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 color_t argcolor(int bits) { return parsecolor(args(), bits == 32); } int parameter_id; EX void shift_arg_formula(ld& x, const reaction_t& r IS(reaction_t())) { shift(); auto par = anims::find_param(&x); if(!par) par = param_f(x, "tmp_parameter_" + its(parameter_id++))->set_reaction(r); par->load_as_animation(args()); } #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 run_arguments(const vector vec) { dynamicval p(pos, 0); dynamicval> orig(argument, vec); read(3); } 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("-sview")) { PHASE(3); start_game(); playermoved = false; transmatrix T = View; shift(); View = parsematrix(args()); println(hlog, "View is set to ", View); current_display->which_copy = View * inverse(T) * current_display->which_copy; } else if(argis("-rotate-up")) { start_game(); shiftmatrix S = ggmatrix(cwt.at->master->move(0)->c7); View = spin90() * spintox(S.T*C0) * View; playermoved = false; } else if(argis("-face-vertex")) { PHASE(3); start_game(); auto &ss = currentmap->get_cellshape(cwt.at); View = cspin90(0, 2) * spintox(ss.vertices_only_local[0]); playermoved = false; } else if(argis("-face-face")) { PHASE(3); start_game(); View = cspin90(0, 2); } else if(argis("-center-vertex")) { PHASE(3); shift(); int i = argi(); shift(); int j = argi(); shift(); int k = argi(); start_game(); auto fh = currentmap->get_cellshape(cwt.at).faces[j][k]; hyperpoint h = View * fh; if(i == 0) { shift_view_to(shiftless(h)); playermoved = false; } if(i == 1) { rotate_view(spintox(h)); rotate_view(cspin90(0, 2)); } } else if(argis("-exit")) { PHASE(3); int t = SDL_GetTicks(); if(t > 1800 * 1000) println(hlog, "Great Success!\n"); else println(hlog, "Success.\n"); fflush(stdout); 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(); } else if(argis("-save-mode")) { save_mode_to_file(shift_args()); } else if(argis("-load-mode")) { try { load_mode_from_file(shift_args()); } catch(hstream_exception& e) { println(hlog, "exception!"); } } // informational else if(argis("-version") || argis("-v")) { printf("HyperRogue version " VER "\n"); exit(0); } else if(argis("-L")) { printf("+ Treasures:\n"); int qty = 0; 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\n"); printf("Not all options are documented, see hyper.cpp\n"); 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); dynamicval ds(delayed_start, true); 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) { return 0; } EX int add2(const string& s, const reaction_t& r) { return 0; } EX int add3(const string& s, const reaction_t& r) { return 0; } EX } #endif }