diff --git a/achievement.cpp b/achievement.cpp index d7170d14..699c32f8 100644 --- a/achievement.cpp +++ b/achievement.cpp @@ -5,9 +5,9 @@ namespace hr { #define NUMLEADER 82 -bool offlineMode = false; +EX bool offlineMode = false; -const char* leadernames[NUMLEADER] = { +EX const char* leadernames[NUMLEADER] = { "Score", "Diamonds", "Gold", "Spice", "Rubies", "Elixirs", "Shards100", "Totems", "Daisies", "Statues", "Feathers", "Sapphires", "Hyperstones", "Time to Win-71", "Turns to Win-71", @@ -73,13 +73,14 @@ const char* leadernames[NUMLEADER] = { #define LB_HALLOWEEN 63 #define LB_RACING 81 -void upload_score(int id, int v); +EX void upload_score(int id, int v); string achievementMessage[3]; int achievementTimer; -vector achievementsReceived; +// achievements received this game +EX vector achievementsReceived; -bool wrongMode(char flags) { +EX bool wrongMode(char flags) { if(cheater) return true; if(flags == rg::global) return false; @@ -106,7 +107,7 @@ bool wrongMode(char flags) { return false; } -void achievement_log(const char* s, char flags) { +EX void achievement_log(const char* s, char flags) { #ifdef PRINT_ACHIEVEMENTS printf("achievement = %s [%d]\n", s, wrongMode(flags)); @@ -136,6 +137,14 @@ void achievement_log(const char* s, char flags) { #endif } +EX void achievement_init(); +EX string myname(); +EX void achievement_close(); +// gain the achievement with the given name. +// flags: 'e' - for Euclidean, 's' - for Shmup, '7' - for heptagonal +// Only awarded if special modes are matched exactly. +EX void achievement_gain(const char* s, char flags IS(0)); + #if ISSTEAM void improveItemScores(); #include "private/hypersteam.cpp" @@ -143,12 +152,16 @@ void improveItemScores(); void achievement_init() {} string myname() { return "Rogue"; } void achievement_close() {} -void achievement_gain(const char* s, char flags) { +// gain the achievement with the given name. +// flags: 'e' - for Euclidean, 's' - for Shmup, '7' - for heptagonal +// Only awarded if special modes are matched exactly. +void achievement_gain(const char* s, char flags IS(0)) { achievement_log(s, flags); } #endif -void achievement_collection(eItem it, int prevgold, int newgold) { +// gain the achievement for collecting a number of 'it'. +EX void achievement_collection(eItem it, int prevgold, int newgold) { if(cheater) return; if(randomPatternsMode) return; int q = items[it]; @@ -456,7 +469,8 @@ void achievement_collection(eItem it, int prevgold, int newgold) { } } -void achievement_count(const string& s, int current, int prev) { +// this is used for 'counting' achievements, such as kill 10 monsters at the same time. +EX void achievement_count(const string& s, int current, int prev) { if(cheater) return; if(shmup::on) return; if(randomPatternsMode) return; @@ -503,7 +517,7 @@ void achievement_count(const string& s, int current, int prev) { int specific_improved = 0; int specific_what = 0; -void improve_score(int i, eItem what) { +EX void improve_score(int i, eItem what) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(haveLeaderboard(i)) updateHi(what, get_currentscore(i)); @@ -516,7 +530,8 @@ void improve_score(int i, eItem what) { #endif } -void achievement_score(int cat, int number) { +// scores for special challenges +EX void achievement_score(int cat, int number) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS if(cheater) return; @@ -537,7 +552,7 @@ void achievement_score(int cat, int number) { #endif } -void improveItemScores() { +EX void improveItemScores() { for(int i=1; i<=12; i++) improve_score(i, eItem(i)); improve_score(17, itOrbYendor); improve_score(18, itFernFlower); @@ -600,7 +615,9 @@ void improveItemScores() { int next_stat_tick; -void achievement_final(bool really_final) { +// gain the final achievements. Called with really=false whenever the user +// looks at their score, and really=true when the game really ends. +EX void achievement_final(bool really_final) { if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS @@ -703,9 +720,9 @@ void achievement_final(bool really_final) { #endif } -bool hadtotalvictory; +EX bool hadtotalvictory; -void check_total_victory() { +EX void check_total_victory() { if(!inv::on) return; if(hadtotalvictory) return; if(!items[itOrbYendor]) return; @@ -716,7 +733,9 @@ void check_total_victory() { achievement_gain("TOTALVICTORY"); } -void achievement_victory(bool hyper) { +// gain the victory achievements. Set 'hyper' to true for +// the Hyperstone victory, and false for the Orb of Yendor victory. +EX void achievement_victory(bool hyper) { DEBBI(DF_STEAM, ("achievement_victory")) if(offlineMode) return; #ifdef HAVE_ACHIEVEMENTS @@ -786,13 +805,15 @@ void achievement_victory(bool hyper) { #endif } -void achievement_pump(); +// call the achievement callbacks +EX void achievement_pump(); #ifndef HAVE_ACHIEVEMENTS void achievement_pump() {} #endif -void achievement_display() { +// display the last achievement gained. +EX void achievement_display() { #ifdef HAVE_ACHIEVEMENTS if(achievementTimer) { int col = (ticks - achievementTimer); @@ -814,18 +835,18 @@ void achievement_display() { #endif } -bool isAscending(int i) { +EX bool isAscending(int i) { return i == 13 || i == 14 || i == 15 || i == 16 || i == 29 || i == 30 || i == 45; }; -int score_default(int i) { +EX int score_default(int i) { if(isAscending(i)) return 1999999999; else return 0; } #ifndef HAVE_ACHIEVEMENTS -int get_sync_status() { return 0; } -void set_priority_board(int) { } +EX int get_sync_status() { return 0; } +EX void set_priority_board(int) { } #endif } diff --git a/archimedean.cpp b/archimedean.cpp index d57a3fd0..e317ada2 100644 --- a/archimedean.cpp +++ b/archimedean.cpp @@ -4,7 +4,7 @@ namespace hr { -namespace arcm { +EX namespace arcm { #if CAP_ARCM @@ -14,30 +14,30 @@ static const int sfCHESS = 4; static const int sfTHREE = 8; static const int sfSEMILINE = 16; -archimedean_tiling current; +EX archimedean_tiling current; // id of vertex in the archimedean tiling // odd numbers = reflected tiles // 0, 2, ..., 2(N-1) = as in the symbol // 2N = bitruncated tile -short& id_of(heptagon *h) { +EX short& id_of(heptagon *h) { return h->zebraval; } // which index in id_of's neighbor list does h->move[0] have -short& parent_index_of(heptagon *h) { +EX short& parent_index_of(heptagon *h) { return h->emeraldval; } // total number of neighbors -int neighbors_of(heptagon *h) { +EX int neighbors_of(heptagon *h) { return isize(current.triangles[id_of(h)]); } -int gcd(int x, int y) { return x ? gcd(y%x, x) : y < 0 ? -y : y; } +EX int gcd(int x, int y) { return x ? gcd(y%x, x) : y < 0 ? -y : y; } void archimedean_tiling::make_match(int a, int i, int b, int j) { if(isize(adjacent[a]) != isize(adjacent[b])) { @@ -583,7 +583,7 @@ struct hrmap_archimedean : hrmap { }; -hrmap *new_map() { return new hrmap_archimedean; } +EX hrmap *new_map() { return new hrmap_archimedean; } heptagon *build_child(heptspin p, pair adj) { indenter ind; @@ -774,8 +774,6 @@ void archimedean_tiling::parse() { } #if CAP_COMMANDLINE -void show(); - int readArgs() { using namespace arg; @@ -838,7 +836,7 @@ bool archimedean_tiling::support_chessboard() { return N % 2 == 0; } -bool pseudohept(cell *c) { +EX bool pseudohept(cell *c) { if(DUAL) return !(c->master->rval0 & 3); int id = id_of(c->master); @@ -849,17 +847,17 @@ bool pseudohept(cell *c) { return false; } -bool chessvalue(cell *c) { +EX bool chessvalue(cell *c) { if(DUAL) return c->master->rval1 - 1; return c->master->fieldval & 1; } -bool linespattern(cell *c) { +EX bool linespattern(cell *c) { return current.flags[id_of(c->master)] & arcm::sfLINE; } -int threecolor(cell *c) { +EX int threecolor(cell *c) { if(current.have_ph) return !arcm::pseudohept(c); else if(PURE) @@ -991,7 +989,7 @@ void next_variation() { start_game(); } -void enable(archimedean_tiling& arct) { +EX void enable(archimedean_tiling& arct) { stop_game(); if(!archimedean) set_variation(eVariation::pure); set_geometry(gArchimedean); @@ -1029,7 +1027,7 @@ function setcanvas(char c) { }; }; -void show() { +EX void show() { if(lastsample < isize(samples)) { string s = samples[lastsample].first; int col = samples[lastsample].second; @@ -1217,15 +1215,15 @@ string archimedean_tiling::world_size() { return s; } -int degree(heptagon *h) { +EX int degree(heptagon *h) { return isize(current.adjacent[id_of(h)]); } -bool is_vertex(heptagon *h) { +EX bool is_vertex(heptagon *h) { return id_of(h) >= 2 * current.N; } -int valence() { +EX int valence() { if(PURE) return arcm::current.N; if(BITRUNCATED) return 3; // in DUAL, usually valence would depend on the vertex. diff --git a/barriers.cpp b/barriers.cpp index ba3c6a64..9459ea97 100644 --- a/barriers.cpp +++ b/barriers.cpp @@ -4,7 +4,7 @@ namespace hr { -bool checkBarriersFront(cellwalker bb, int q, bool cross) { +EX bool checkBarriersFront(cellwalker bb, int q, bool cross) { if(!ctof(bb.at)) return false; @@ -28,15 +28,15 @@ bool checkBarriersFront(cellwalker bb, int q, bool cross) { return checkBarriersBack(bb, q); } -bool hasbardir(cell *c) { +EX bool hasbardir(cell *c) { return c->bardir != NODIR && c->bardir != NOBARRIERS; } -void preventbarriers(cell *c) { +EX void preventbarriers(cell *c) { if(c && c->bardir == NODIR) c->bardir = NOBARRIERS; } -bool checkBarriersBack(cellwalker bb, int q, bool cross) { +EX bool checkBarriersBack(cellwalker bb, int q, bool cross) { // printf("back, %p, s%d\n", bb.at, bb.spin); // if(mark) { printf("mpdist = %d [%d] bardir = %d spin=%d q=%d cross=%d\n", bb.at->mpdist, BARLEV, bb.at->bardir, bb.spin, q, cross); } @@ -61,11 +61,11 @@ bool checkBarriersBack(cellwalker bb, int q, bool cross) { } // warp coasts use a different algorithm when has_nice_dual() is on -bool warped_version(eLand l1, eLand l2) { +EX bool warped_version(eLand l1, eLand l2) { return (has_nice_dual() && (l1 == laWarpCoast || l1 == laWarpSea || l2 == laWarpSea || l2 == laWarpCoast)) || (VALENCE == 3); } -bool checkBarriersNowall(cellwalker bb, int q, int dir, eLand l1=laNone, eLand l2=laNone) { +EX bool checkBarriersNowall(cellwalker bb, int q, int dir, eLand l1 IS(laNone), eLand l2 IS(laNone)) { if(bb.at->mpdist < BARLEV && l1 == l2) return false; if(bb.cpeek()->bardir != NODIR && l1 == l2) return false; if(bb.at->bardir != NODIR && l1 == l2) return false; @@ -106,7 +106,7 @@ bool checkBarriersNowall(cellwalker bb, int q, int dir, eLand l1=laNone, eLand l return checkBarriersNowall(bb, q+1, -dir, l2, l1); } -eWall getElementalWall(eLand l) { +EX eWall getElementalWall(eLand l) { if(l == laEAir) return waChasm; if(l == laEEarth) return waStone; if(l == laEFire) return waEternalFire; @@ -114,7 +114,7 @@ eWall getElementalWall(eLand l) { return waNone; } -void setbarrier(cell *c) { +EX void setbarrier(cell *c) { if(isSealand(c->barleft) && isSealand(c->barright)) { bool setbar = ctof(c); if(c->barleft == laKraken || c->barright == laKraken) @@ -144,7 +144,7 @@ void setbarrier(cell *c) { } } -void setland(cell *c, eLand l) { +EX void setland(cell *c, eLand l) { if(c->land != l) { c->landparam = 0; } @@ -154,18 +154,18 @@ void setland(cell *c, eLand l) { c->land = l; } -void extendcheck(cell *c) { +EX void extendcheck(cell *c) { return; if(BITRUNCATED && c->landparam == 0 && c->barleft != NOWALLSEP) { raiseBuggyGeneration(c, "extend error"); } } -bool mirrorwall(cell *c) { +EX bool mirrorwall(cell *c) { return c->barleft == laMirrored || c->barright == laMirrored; } -void extendBarrierFront(cell *c) { +EX void extendBarrierFront(cell *c) { limitgen("extend front %p\n", c); if(buggyGeneration) return; int ht = c->landparam; @@ -215,7 +215,7 @@ void extendBarrierFront(cell *c) { } } -void extendBarrierBack(cell *c) { +EX void extendBarrierBack(cell *c) { limitgen("extend back %p\n", c); if(buggyGeneration) return; int ht = c->landparam; @@ -247,7 +247,7 @@ void extendBarrierBack(cell *c) { extendBarrier(bb.at); } -void extendNowall(cell *c) { +EX void extendNowall(cell *c) { c->barleft = NOWALLSEP_USED; cellwalker cw(c, c->bardir); @@ -304,7 +304,7 @@ void extendNowall(cell *c) { bool gotit = false; -void extendCR5(cell *c) { +EX void extendCR5(cell *c) { if(!BITRUNCATED) return; // if(c->barright == laCrossroads5) extendCR5(c); eLand forbidden = c->barleft; @@ -329,16 +329,14 @@ void extendCR5(cell *c) { } } -bool isbar4(cell *c) { +EX bool isbar4(cell *c) { return c->wall == waBarrier || c->land == laElementalWall || c->land == laMirrorWall || c->land == laMirrorWall2 || c->land == laMercuryRiver; } -void extend3D(cell *c); - -void extendBarrier(cell *c) { +EX void extendBarrier(cell *c) { limitgen("extend barrier %p\n", c); if(buggyGeneration) return; @@ -425,7 +423,7 @@ void extendBarrier(cell *c) { if(c->barright == laCrossroads5) extendCR5(c); } -void buildBarrierForce(cell *c, int d, eLand l) { +EX void buildBarrierForce(cell *c, int d, eLand l) { c->bardir = d; eLand oldland = c->land; if(oldland == laNone) { @@ -440,7 +438,7 @@ void buildBarrierForce(cell *c, int d, eLand l) { extendcheck(c); } -void buildBarrier(cell *c, int d, eLand l) { +EX void buildBarrier(cell *c, int d, eLand l IS(laNone)) { d %= 7; cellwalker bb(c, d); @@ -448,7 +446,7 @@ void buildBarrier(cell *c, int d, eLand l) { buildBarrierForce(c, d, l); } -bool buildBarrier6(cellwalker cw, int type) { +EX bool buildBarrier6(cellwalker cw, int type) { limitgen("build6 %p/%d (%d)\n", cw.at, cw.spin, type); cellwalker b[4]; @@ -559,9 +557,7 @@ bool buildBarrier6(cellwalker cw, int type) { return true; } - - -bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) { +EX bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) { limitgen("build4 %p\n", c); if(buggyGeneration) return true; d %= 7; @@ -622,7 +618,7 @@ bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) { return true; } -void buildBarrierStrong(cell *c, int d, bool oldleft, eLand newland) { +EX void buildBarrierStrong(cell *c, int d, bool oldleft, eLand newland) { d %= 7; cellwalker bb(c, d); @@ -635,11 +631,11 @@ void buildBarrierStrong(cell *c, int d, bool oldleft, eLand newland) { extendcheck(bb.at); } -void buildBarrierStrong(cell *c, int d, bool oldleft) { +EX void buildBarrierStrong(cell *c, int d, bool oldleft) { buildBarrierStrong(c, d, oldleft, getNewLand(c->land)); } -void buildCrossroads2(cell *c) { +EX void buildCrossroads2(cell *c) { if(buggyGeneration) return; @@ -735,7 +731,7 @@ void buildCrossroads2(cell *c) { } #if MAXMDIM >= 4 -void extend3D(cell *c) { +EX void extend3D(cell *c) { eLand l1 = c->land; c->barleft = NOWALLSEP_USED; @@ -772,7 +768,7 @@ void extend3D(cell *c) { bool built = false; -bool buildBarrier3D(cell *c, eLand l2, int forced_dir) { +EX bool buildBarrier3D(cell *c, eLand l2, int forced_dir) { if(forced_dir == NODIR) { for(int t=0; tmove(t) || c->move(t)->mpdist > c->mpdist) && buildBarrier3D(c, l2, t)) return true; return false; @@ -815,7 +811,7 @@ bool buildBarrier3D(cell *c, eLand l2, int forced_dir) { } #endif -bool buildBarrierNowall(cell *c, eLand l2, int forced_dir) { +EX bool buildBarrierNowall(cell *c, eLand l2, int forced_dir) { if(geometry == gBinary4) return false; #if MAXMDIM >= 4 diff --git a/basegraph.cpp b/basegraph.cpp index 364cf653..54371e58 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -3,12 +3,12 @@ namespace hr { -display_data default_display; -display_data *current_display = &default_display; +EX display_data default_display; +EX display_data *current_display = &default_display; -unsigned backcolor = 0; -unsigned bordcolor = 0; -unsigned forecolor = 0xFFFFFF; +EX unsigned backcolor = 0; +EX unsigned bordcolor = 0; +EX unsigned forecolor = 0xFFFFFF; int utfsize(char c) { unsigned char cu = c; @@ -18,8 +18,8 @@ int utfsize(char c) { return 4; } -int get_sightrange() { return getDistLimit() + sightrange_bonus; } -int get_sightrange_ambush() { return max(get_sightrange(), ambush_distance); } +EX int get_sightrange() { return getDistLimit() + sightrange_bonus; } +EX int get_sightrange_ambush() { return max(get_sightrange(), ambush_distance); } namespace stereo { eStereo mode; @@ -66,11 +66,12 @@ TTF_Font *font[256]; #endif #if CAP_SDL -SDL_Surface *s, *s_screen; +EX SDL_Surface *s; +EX SDL_Surface *s_screen; color_t qpixel_pixel_outside; -color_t& qpixel(SDL_Surface *surf, int x, int y) { +EX color_t& qpixel(SDL_Surface *surf, int x, int y) { if(x<0 || y<0 || x >= surf->w || y >= surf->h) return qpixel_pixel_outside; char *p = (char*) surf->pixels; p += y * surf->pitch; @@ -137,7 +138,7 @@ bool fading = false; ld fadeout = 1; -color_t darkened(color_t c) { +EX color_t darkened(color_t c) { if(inmirrorcount&1) c = gradient(c, winf[waMirror].color, 0, 0.5, 1); else if(inmirrorcount) @@ -152,21 +153,23 @@ color_t darkened(color_t c) { return c; } -color_t darkena3(color_t c, int lev, int a) { +EX color_t darkena3(color_t c, int lev, int a) { return (darkenedby(c, lev) << 8) + a; } -color_t darkena(color_t c, int lev, int a) { +EX color_t darkena(color_t c, int lev, int a) { return darkena3(c, lev, DIM == 3 ? 255 : a); } #if !CAP_GL void setcameraangle(bool b) { } -#else +#endif -bool shaderside_projection; +#if CAP_GL -void start_projection(int ed, bool perspective) { +EX bool shaderside_projection; + +EX void start_projection(int ed, bool perspective) { glhr::use_projection(); glhr::new_projection(); shaderside_projection = perspective; @@ -197,7 +200,7 @@ glhr::glmatrix model_orientation_gl() { } tuple last_projection; -bool new_projection_needed; +EX bool new_projection_needed; void display_data::set_all(int ed) { auto t = this; @@ -426,11 +429,11 @@ void display_data::set_viewport(int ed) { glViewport(xtop, ytop, xsize, ysize); } -bool model_needs_depth() { +EX bool model_needs_depth() { return DIM == 3 || pmodel == mdBall; } -void setGLProjection(color_t col) { +EX void setGLProjection(color_t col IS(backcolor)) { DEBBI(DF_GRAPH, ("setGLProjection")); GLERR("pre_setGLProjection"); @@ -643,20 +646,20 @@ int gl_width(int size, const char *s) { return x; } -namespace glhr { void texture_vertices(GLfloat *f, int qty, int stride = 2) { - WITHSHADER( - glVertexAttribPointer(aTexture, stride, GL_FLOAT, GL_FALSE, stride * sizeof(GLfloat), f);, - glTexCoordPointer(stride, GL_FLOAT, 0, f); - ) - } - void oldvertices(GLfloat *f, int qty) { - WITHSHADER( - glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, SHDIM * sizeof(GLfloat), f);, - glVertexPointer(SHDIM, GL_FLOAT, 0, f); - ) - // #endif +namespace glhr { + void texture_vertices(GLfloat *f, int qty, int stride = 2) { + WITHSHADER( + glVertexAttribPointer(aTexture, stride, GL_FLOAT, GL_FALSE, stride * sizeof(GLfloat), f);, + glTexCoordPointer(stride, GL_FLOAT, 0, f); + ) + } + void oldvertices(GLfloat *f, int qty) { + WITHSHADER( + glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, SHDIM * sizeof(GLfloat), f);, + glVertexPointer(SHDIM, GL_FLOAT, 0, f); + ) + } } - } vector tver; @@ -737,9 +740,9 @@ bool gl_print(int x, int y, int shift, int size, const char *s, color_t color, i #endif -purehookset hooks_resetGL; +EX purehookset hooks_resetGL; -void resetGL() { +EX void resetGL() { DEBBI(DF_INIT | DF_GRAPH, ("reset GL")) callhooks(hooks_resetGL); #if CAP_GLFONT @@ -828,7 +831,7 @@ bool displaystr(int x, int y, int shift, int size, char const *s, color_t color, } #else -bool displaystr(int x, int y, int shift, int size, const char *str, color_t color, int align) { +EX bool displaystr(int x, int y, int shift, int size, const char *str, color_t color, int align) { if(strlen(str) == 0) return false; @@ -891,11 +894,11 @@ bool displaystr(int x, int y, int shift, int size, const char *str, color_t colo #endif } -bool displaystr(int x, int y, int shift, int size, const string &s, color_t color, int align) { +EX bool displaystr(int x, int y, int shift, int size, const string &s, color_t color, int align) { return displaystr(x, y, shift, size, s.c_str(), color, align); } -bool displayfrSP(int x, int y, int sh, int b, int size, const string &s, color_t color, int align, int p) { +EX bool displayfrSP(int x, int y, int sh, int b, int size, const string &s, color_t color, int align, int p) { if(b) { displaystr(x-b, y, 0, size, s, p, align); displaystr(x+b, y, 0, size, s, p, align); @@ -912,11 +915,11 @@ bool displayfrSP(int x, int y, int sh, int b, int size, const string &s, color_t return displaystr(x, y, 0, size, s, color, align); } -bool displayfr(int x, int y, int b, int size, const string &s, color_t color, int align) { +EX bool displayfr(int x, int y, int b, int size, const string &s, color_t color, int align) { return displayfrSP(x, y, 0, b, size, s, color, align, poly_outline>>8); } -bool displaychr(int x, int y, int shift, int size, char chr, color_t col) { +EX bool displaychr(int x, int y, int shift, int size, char chr, color_t col) { char buf[2]; buf[0] = chr; buf[1] = 0; @@ -928,7 +931,7 @@ vector msgs; vector gamelog; -void flashMessages() { +EX void flashMessages() { for(int i=0; i& log) { } } -void clearMessages() { msgs.clear(); } +EX void clearMessages() { msgs.clear(); } -void addMessage(string s, char spamtype) { +EX void addMessage(string s, char spamtype) { DEBB(DF_MSG, ("addMessage: ", s)); msginfo m; @@ -976,15 +979,15 @@ void addMessage(string s, char spamtype) { addMessageToLog(m, msgs); } -color_t colormix(color_t a, color_t b, color_t c) { +EX color_t colormix(color_t a, color_t b, color_t c) { for(int p=0; p<3; p++) part(a, p) = part(a,p) + (part(b,p) - part(a,p)) * part(c,p) / 255; return a; } -int rhypot(int a, int b) { return (int) sqrt(a*a - b*b); } +EX int rhypot(int a, int b) { return (int) sqrt(a*a - b*b); } -ld realradius() { +EX ld realradius() { ld vradius = current_display->radius; if(sphere) { if(sphereflipped()) @@ -998,7 +1001,7 @@ ld realradius() { return vradius; } -void drawmessage(const string& s, int& y, color_t col) { +EX void drawmessage(const string& s, int& y, color_t col) { int rrad = (int) realradius(); int space; if(dual::state) @@ -1034,7 +1037,7 @@ void drawmessage(const string& s, int& y, color_t col) { return; } -void drawmessages() { +EX void drawmessages() { DEBBI(DF_GRAPH, ("draw messages")); int i = 0; int t = ticks; @@ -1069,7 +1072,7 @@ void drawmessages() { } } -color_t gradient(color_t c0, color_t c1, ld v0, ld v, ld v1) { +EX color_t gradient(color_t c0, color_t c1, ld v0, ld v, ld v1) { int vv = int(256 * ((v-v0) / (v1-v0))); color_t c = 0; for(int a=0; a<3; a++) { @@ -1080,7 +1083,7 @@ color_t gradient(color_t c0, color_t c1, ld v0, ld v, ld v1) { return c; } -void drawCircle(int x, int y, int size, color_t color, color_t fillcolor) { +EX void drawCircle(int x, int y, int size, color_t color, color_t fillcolor IS(0)) { if(size < 0) size = -size; #if CAP_GL && CAP_POLY if(vid.usingGL) { @@ -1131,7 +1134,7 @@ void drawCircle(int x, int y, int size, color_t color, color_t fillcolor) { #endif } -void displayButton(int x, int y, const string& name, int key, int align, int rad) { +EX void displayButton(int x, int y, const string& name, int key, int align, int rad IS(0)) { if(displayfr(x, y, rad, vid.fsize, name, 0x808080, align)) { displayfr(x, y, rad, vid.fsize, name, 0xFFFF00, align); getcstat = key; @@ -1141,14 +1144,14 @@ void displayButton(int x, int y, const string& name, int key, int align, int rad char mousekey = 'n'; char newmousekey; -void displaymm(char c, int x, int y, int rad, int size, const string& title, int align) { +EX void displaymm(char c, int x, int y, int rad, int size, const string& title, int align) { if(displayfr(x, y, rad, size, title, c == mousekey ? 0xFF8000 : 0xC0C0C0, align)) { displayfr(x, y, rad, size, title, 0xFFFF00, align); getcstat = SETMOUSEKEY, newmousekey = c; } } -bool displayButtonS(int x, int y, const string& name, color_t col, int align, int size) { +EX bool displayButtonS(int x, int y, const string& name, color_t col, int align, int size) { if(displaystr(x, y, 0, size, name, col, align)) { displaystr(x, y, 0, size, name, 0xFFFF00, align); return true; @@ -1156,7 +1159,7 @@ bool displayButtonS(int x, int y, const string& name, color_t col, int align, in else return false; } -void displayColorButton(int x, int y, const string& name, int key, int align, int rad, color_t color, color_t color2) { +EX void displayColorButton(int x, int y, const string& name, int key, int align, int rad, color_t color, color_t color2 IS(0)) { if(displayfr(x, y, rad, vid.fsize, name, color, align)) { if(color2) displayfr(x, y, rad, vid.fsize, name, color2, align); getcstat = key; @@ -1171,22 +1174,22 @@ ld textscale() { bool setfsize = true; -bool vsync_off; +EX bool vsync_off; -void do_setfsize() { +EX void do_setfsize() { dual::split_or_do([&] { vid.fsize = min(vid.yres * fontscale/ 3200, vid.xres * fontscale/ 4800), setfsize = false; }); } -void disable_vsync() { +EX void disable_vsync() { #if !ISMOBWEB SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 ); #endif } #if CAP_SDL -void setvideomode() { +EX void setvideomode() { DEBBI(DF_INIT | DF_GRAPH, ("setvideomode")); @@ -1251,9 +1254,9 @@ void setvideomode() { } #endif -bool noGUI = false; +EX bool noGUI = false; -void initgraph() { +EX void initgraph() { DEBBI(DF_INIT | DF_GRAPH, ("initgraph")); @@ -1334,7 +1337,7 @@ void initgraph() { } -void cleargraph() { +EX void cleargraph() { DEBBI(DF_INIT, ("clear graph")); #if CAP_SDLTTF for(int i=0; i<256; i++) if(font[i]) TTF_CloseFont(font[i]); @@ -1350,7 +1353,7 @@ void cleargraph() { #endif } -int calcfps() { +EX int calcfps() { #define CFPS 30 static int last[CFPS], lidx = 0; int ct = ticks; @@ -1361,18 +1364,18 @@ int calcfps() { return (1000 * CFPS) / ret; } -namespace subscreens { +EX namespace subscreens { vector player_displays; bool in; - int current_player; + EX int current_player; - bool is_current_player(int id) { + EX bool is_current_player(int id) { if(!in) return true; return id == current_player; } - void prepare() { + EX void prepare() { int N = multi::players; if(N > 1) { player_displays.resize(N, *current_display); @@ -1392,7 +1395,7 @@ namespace subscreens { } } - bool split(reaction_t what) { + EX bool split(reaction_t what) { using namespace racing; if(in) return false; if(!racing::on && !(shmup::on && DIM == 3)) return false; diff --git a/bigstuff.cpp b/bigstuff.cpp index 96cec772..9e9d619a 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -9,11 +9,11 @@ namespace hr { -int newRoundTableRadius() { +EX int newRoundTableRadius() { return 28 + 2 * items[itHolyGrail]; } -int getAnthraxData(cell *c, bool b) { +EX int getAnthraxData(cell *c, bool b) { int d = celldistAlt(c); int rad = 28 + 3 * anthraxBonus; while(d < -rad) { @@ -29,14 +29,14 @@ int getAnthraxData(cell *c, bool b) { return d; } -int roundTableRadius(cell *c) { +EX int roundTableRadius(cell *c) { if(eubinary) return 28; if(tactic::on) return getAnthraxData(c, true); if(!c->master->alt) return 28; return c->master->alt->alt->emeraldval & GRAIL_RADIUS_MASK; } -int celldistAltRelative(cell *c) { +EX int celldistAltRelative(cell *c) { #if CAP_CRYSTAL if(geometry == gCrystal) return crystal::dist_relative(c); #endif @@ -51,7 +51,7 @@ int celldistAltRelative(cell *c) { return celldistAlt(c) - roundTableRadius(c); } -int euclidAlt(short x, short y) { +EX int euclidAlt(short x, short y) { if(among(specialland, laTemple, laClearing, laCanvas)) { if(euclid6) return max(int(x), x+y); @@ -78,7 +78,7 @@ int euclidAlt(short x, short y) { else return eudist(x-(a4 ? 21 : 20), y-10); } -int cylinder_alt(cell *c) { +EX int cylinder_alt(cell *c) { if(specialland == laPrincessQuest) return celldistance(c, vec_to_cellwalker(pair_to_vec(EPX, EPY)).at); if(specialland == laCamelot) @@ -93,14 +93,14 @@ int cylinder_alt(cell *c) { const int NOCOMPASS = 1000000; -int compassDist(cell *c) { +EX int compassDist(cell *c) { if(sphere || quotient) return 0; if(eubinary || c->master->alt) return celldistAlt(c); if(isHaunted(c->land) || c->land == laGraveyard) return getHauntedDepth(c); return NOCOMPASS; } -cell *findcompass(cell *c) { +EX cell *findcompass(cell *c) { int d = compassDist(c); if(d == NOCOMPASS) return NULL; @@ -119,7 +119,7 @@ cell *findcompass(cell *c) { return c; } -bool grailWasFound(cell *c) { +EX bool grailWasFound(cell *c) { if(eubinary || quotient || sphere) return items[itHolyGrail]; return c->master->alt->alt->emeraldval & GRAIL_FOUND; } @@ -173,7 +173,7 @@ void hrmap::generateAlts(heptagon *h, int levs, bool link_cdata) { } } -heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { +EX heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special IS(0)) { // check for direction int gdir = -1; @@ -262,7 +262,7 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special) { //for(int d=rad; d>=0; d--) printf("%3d. %p {%d}\n", d, cx[d]->master, cx[d]->master->alt->distance); } -void beCIsland(cell *c) { +EX void beCIsland(cell *c) { int i = hrand(3); if(i == 0) c->wall = waCIsland; if(i == 1) c->wall = waCIsland2; @@ -270,7 +270,7 @@ void beCIsland(cell *c) { return; } -void generateTreasureIsland(cell *c) { +EX void generateTreasureIsland(cell *c) { if(!eubinary) currentmap->generateAlts(c->master); if(isOnCIsland(c)) return; @@ -332,11 +332,9 @@ void generateTreasureIsland(cell *c) { // equidistants -extern bool generatingEquidistant; +EX bool generatingEquidistant = false; -bool generatingEquidistant = false; - -cell *buildAnotherEquidistant(cell *c, int radius) { +EX cell *buildAnotherEquidistant(cell *c, int radius) { int gdir = -1; for(int i=0; itype; i++) { if(c->move(i) && c->move(i)->mpdist < c->mpdist) gdir = i; @@ -427,7 +425,7 @@ cell *buildAnotherEquidistant(cell *c, int radius) { return c2; } -void buildAnotherEquidistant(cell *c) { +EX void buildAnotherEquidistant(cell *c) { //printf("building another coast\n"); if(yendor::on) return; @@ -441,7 +439,7 @@ void buildAnotherEquidistant(cell *c) { generatingEquidistant = false; } -int coastval(cell *c, eLand base) { +EX int coastval(cell *c, eLand base) { if(!c) return UNKNOWN; if(c->land == laNone) return UNKNOWN; if(base == laGraveyard) { @@ -466,7 +464,7 @@ int coastval(cell *c, eLand base) { return c->landparam; } -bool checkInTree(cell *c, int maxv) { +EX bool checkInTree(cell *c, int maxv) { if(c->landparam <= 3) return false; if(!maxv && WDIM == 3 && binarytiling) { forCellEx(c2, c) if(c2->landflags) return true; @@ -486,7 +484,7 @@ struct loopchecker { ~loopchecker() { loopval--; } }; -void buildEquidistant(cell *c) { +EX void buildEquidistant(cell *c) { loopchecker lc; // sometimes crashes in Archimedean if(loopval > 100) { c->landparam = 0; return; } @@ -751,7 +749,7 @@ void buildEquidistant(cell *c) { buildAnotherEquidistant(c); } -cell *randomDown(cell *c) { +EX cell *randomDown(cell *c) { cell *tab[MAX_EDGE]; int q=0; for(int i=0; itype; i++) @@ -762,7 +760,7 @@ cell *randomDown(cell *c) { return tab[hrand(q)]; } -int edgeDepth(cell *c) { +EX int edgeDepth(cell *c) { if(c->land == laIvoryTower || c->land == laEndorian || c->land == laDungeon || c->land == laWestWall) return coastvalEdge(c); else if(c->land != laBarrier) { @@ -772,7 +770,7 @@ int edgeDepth(cell *c) { return 0; } -int getHauntedDepth(cell *c) { +EX int getHauntedDepth(cell *c) { if((tactic::on || euclid) && c->land == laHaunted) return celldist(c); if(c->land == laHaunted) return c->landparam; if(c->land == laHauntedWall) return 0; @@ -780,7 +778,7 @@ int getHauntedDepth(cell *c) { return -100; } -int towerval(cell *c, const cellfunction& cf) { +EX int towerval(cell *c, const cellfunction& cf) { cell *cp1 = ts::left_of(c, cf); if(!cp1) return 0; int under = 0; @@ -791,7 +789,7 @@ int towerval(cell *c, const cellfunction& cf) { /* other geometries */ -void setLandWeird(cell *c) { +EX void setLandWeird(cell *c) { // replaced with standard CR4 /* if(specialland == laIvoryTower || specialland == laEndorian || specialland == laDungeon || specialland == laOcean) { int d = celldist(c) - (getDistLimit() - 2); @@ -802,7 +800,7 @@ void setLandWeird(cell *c) { } */ } -void setLandQuotient(cell *c) { +EX void setLandQuotient(cell *c) { setland(c, specialland); int fv = zebra40(c); if(fv/4 == 4 || fv/4 == 6 || fv/4 == 5 || fv/4 == 10) fv ^= 2; @@ -822,7 +820,7 @@ void setLandQuotient(cell *c) { if(specialland == laWestWall) c->land = laCrossroads4; } -void elementalXY(cell *c, int x, int y, bool make_wall) { +EX void elementalXY(cell *c, int x, int y, bool make_wall) { if(x > 0 && y > 0) setland(c, laEFire); else if(x > 0 && y < 0) setland(c, laEAir); else if(x < 0 && y < 0) setland(c, laEWater); @@ -841,7 +839,7 @@ void elementalXY(cell *c, int x, int y, bool make_wall) { c->wall = getElementalWall(hrand(2) ? c->barleft : c->barright); } -void setLandSphere(cell *c) { +EX void setLandSphere(cell *c) { setland(c, specialland); if(specialland == laWarpCoast) setland(c, getHemisphere(c, 0) > 0 ? laWarpCoast : laWarpSea); @@ -877,12 +875,12 @@ vector euland; map euland3; map euland3_hash; -eLand& get_euland(int c) { +EX eLand& get_euland(int c) { euland.resize(max_vec); return euland[c & (max_vec-1)]; } -void clear_euland(eLand first) { +EX void clear_euland(eLand first) { euland.resize(max_vec); for(int i=0; imaster->distance)); @@ -964,7 +962,7 @@ void setLandSol(cell *c) { } } -void setLandNil(cell *c) { +EX void setLandNil(cell *c) { setland(c, specialland); if(chaosmode) { @@ -1018,7 +1016,7 @@ void setLandNil(cell *c) { } } -void setLandEuclid(cell *c) { +EX void setLandEuclid(cell *c) { #if CAP_RACING if(racing::track_ready) { setland(c, laMemory); @@ -1141,14 +1139,14 @@ void setLandEuclid(cell *c) { } } -eLand get_euland3(int x) { +EX eLand get_euland3(int x) { if(euland3.count(x)) return euland3[x]; if(x > 0) return euland3[x] = getNewLand(euland3[x-1]); if(x < 0) return euland3[x] = getNewLand(euland3[x+1]); return euland3[x] = laCrossroads; } -void set_euland3(cell *c, int co10, int co11, int alt, int hash) { +EX void set_euland3(cell *c, int co10, int co11, int alt, int hash) { if(chaosmode) { setland(c, get_euland3(gdiv(co10, 60))); @@ -1206,7 +1204,7 @@ void set_euland3(cell *c, int co10, int co11, int alt, int hash) { // the main big stuff function -bool quickfind(eLand l) { +EX bool quickfind(eLand l) { if(l == cheatdest) return true; if(l == specialland && (weirdhyperbolic || specialland != laIce || cheater)) return true; #if CAP_TOUR @@ -1219,7 +1217,7 @@ bool quickfind(eLand l) { #define I2000 (INVLUCK?600:2000) #define I10000 (INVLUCK?3000:10000) -int wallchance(cell *c, bool deepOcean) { +EX int wallchance(cell *c, bool deepOcean) { eLand l = c->land; return showoff ? (cwt.at->mpdist > 7 ? 0 : 10000) : @@ -1252,12 +1250,12 @@ int wallchance(cell *c, bool deepOcean) { 50; } -bool horo_ok() { +EX bool horo_ok() { // do the horocycles work in the current geometry? return hyperbolic && !binarytiling && !archimedean && !penrose; } -bool gp_wall_test() { +EX bool gp_wall_test() { #if CAP_GP if(GOLDBERG) return hrand(gp::dist_3()) == 0; #endif @@ -1267,7 +1265,7 @@ bool gp_wall_test() { return true; } -bool deep_ocean_at(cell *c, cell *from) { +EX bool deep_ocean_at(cell *c, cell *from) { if(generatingEquidistant) return false; @@ -1297,13 +1295,13 @@ bool deep_ocean_at(cell *c, cell *from) { return false; } -bool good_for_wall(cell *c) { +EX bool good_for_wall(cell *c) { if(archimedean) return true; if(WDIM == 3) return true; return pseudohept(c); } -void buildBigStuff(cell *c, cell *from) { +EX void buildBigStuff(cell *c, cell *from) { if(sphere || quotient || nonisotropic || (penrose && !binarytiling)) return; if(chaosmode > 1) return; bool deepOcean = deep_ocean_at(c, from); @@ -1455,7 +1453,7 @@ void buildBigStuff(cell *c, cell *from) { if(hasbardir(c)) extendBarrier(c); } -bool openplains(cell *c) { +EX bool openplains(cell *c) { if(chaosmode) { forCellEx(c2, c) if(c2->land != laHunting) return false; return true; @@ -1481,7 +1479,7 @@ bool openplains(cell *c) { } } -void buildCamelotWall(cell *c) { +EX void buildCamelotWall(cell *c) { c->wall = waCamelot; for(int i=0; itype; i++) { cell *c2 = createMov(c, i); @@ -1490,13 +1488,13 @@ void buildCamelotWall(cell *c) { } } -bool no_barriers_in_radius(cell *c, int rad) { +EX bool no_barriers_in_radius(cell *c, int rad) { celllister cl(c, 2, 1000000, NULL); for(cell *c: cl.lst) if(c->bardir != NODIR) return false; return true; } -void buildCamelot(cell *c) { +EX void buildCamelot(cell *c) { int d = celldistAltRelative(c); if(tactic::on || (d <= 14 && roundTableRadius(c) > 20)) { if(!eubinary) currentmap->generateAlts(c->master); @@ -1568,14 +1566,14 @@ void buildCamelot(cell *c) { } } -int masterAlt(cell *c) { +EX int masterAlt(cell *c) { #if MAXMDIM >= 4 if(WDIM == 3 && hyperbolic) return reg3::altdist(c->master); #endif return c->master->alt->distance; } -void moreBigStuff(cell *c) { +EX void moreBigStuff(cell *c) { if((bearsCamelot(c->land) && !euclid && !quotient && !nil) || c->land == laCamelot) if(eubinary || binarytiling || c->master->alt) if(!(binarytiling && specialland != laCamelot)) @@ -1704,7 +1702,7 @@ void moreBigStuff(cell *c) { } } -void generate_mines() { +EX void generate_mines() { vector candidates; for(cell *c: currentmap->allcells()) if(c->wall == waMineUnknown) @@ -1715,9 +1713,9 @@ void generate_mines() { for(int i=0; iwall = waMineMine; } -vector currentlands; +EX vector currentlands; -void pregen() { +EX void pregen() { currentlands.clear(); if(chaosmode > 1) for(eLand l: land_over) diff --git a/blizzard.cpp b/blizzard.cpp index b3552af2..687c403c 100644 --- a/blizzard.cpp +++ b/blizzard.cpp @@ -27,7 +27,7 @@ struct blizzardcell { map blizzardcells; -void set_blizzard_frame(cell *c, int frameid) { +EX void set_blizzard_frame(cell *c, int frameid) { blizzardcells[c].frame = frameid; } @@ -42,7 +42,7 @@ blizzardcell* getbcell(cell *c) { return bcells[i]; } -void drawBlizzards() { +EX void drawBlizzards() { #if CAP_SHAPES && CAP_FIELD poly_outline = OUTLINE_NONE; auto it = blizzardcells.begin(); @@ -207,7 +207,7 @@ void drawBlizzards() { vector arrowtraps; -void drawArrowTraps() { +EX void drawArrowTraps() { for(cell *c: arrowtraps) { auto r = traplimits(c); diff --git a/cell.cpp b/cell.cpp index 91b067d0..ecdb5334 100644 --- a/cell.cpp +++ b/cell.cpp @@ -5,18 +5,16 @@ namespace hr { -int dirdiff(int dd, int t) { +EX int dirdiff(int dd, int t) { dd %= t; if(dd<0) dd += t; if(t-dd < dd) dd = t-dd; return dd; } -int cellcount = 0; +EX int cellcount = 0; -void initcell(cell *c); // from game.cpp - -cell *newCell(int type, heptagon *master) { +EX cell *newCell(int type, heptagon *master) { cell *c = tailored_alloc (type); c->type = type; c->master = master; @@ -26,10 +24,10 @@ cell *newCell(int type, heptagon *master) { // -- hrmap --- -hrmap *currentmap; -vector allmaps; +EX hrmap *currentmap; +EX vector allmaps; -hrmap *newAltMap(heptagon *o) { return new hrmap_hyperbolic(o); } +EX hrmap *newAltMap(heptagon *o) { return new hrmap_hyperbolic(o); } // --- hyperbolic geometry --- hrmap_hyperbolic::hrmap_hyperbolic(heptagon *o) { origin = o; } @@ -71,7 +69,7 @@ hrmap_hyperbolic::hrmap_hyperbolic() { } // very similar to createMove in heptagon.cpp -cell *createMov(cell *c, int d) { +EX cell *createMov(cell *c, int d) { if(d<0 || d>= c->type) { printf("ERROR createmov\n"); } @@ -159,7 +157,7 @@ cell *createMov(cell *c, int d) { return c->move(d); } -void eumerge(cell* c1, int s1, cell *c2, int s2, bool mirror) { +EX void eumerge(cell* c1, int s1, cell *c2, int s2, bool mirror) { if(!c2) return; c1->move(s1) = c2; c1->c.setspin(s1, s2, mirror); c2->move(s2) = c1; c2->c.setspin(s2, s1, mirror); @@ -167,13 +165,13 @@ void eumerge(cell* c1, int s1, cell *c2, int s2, bool mirror) { // map, cell*> euclidean; -euc_pointer euclideanAt(int vec) { +EX euc_pointer euclideanAt(int vec) { if(fulltorus) { printf("euclideanAt called\n"); exit(1); } hrmap_euclidean* euc = dynamic_cast (currentmap); return euc->at(vec); } -euc_pointer euclideanAtCreate(int vec) { +EX euc_pointer euclideanAtCreate(int vec) { euc_pointer ep = euclideanAt(vec); cell*& c = *ep.first; if(!c) { @@ -200,7 +198,7 @@ euc_pointer euclideanAtCreate(int vec) { hookset *hooks_newmap; // initializer (also inits origin from heptagon.cpp) -void initcells() { +EX void initcells() { DEBB(DF_INIT, ("initcells")); hrmap* res = callhandlers((hrmap*)nullptr, hooks_newmap); @@ -240,7 +238,7 @@ void initcells() { // origin->emeraldval = } -void clearcell(cell *c) { +EX void clearcell(cell *c) { if(!c) return; DEBB(DF_MEMORY, (format("c%d %p\n", c->type, c))); for(int t=0; ttype; t++) if(c->move(t)) { @@ -256,7 +254,7 @@ void clearcell(cell *c) { tailored_delete(c); } -heptagon deletion_marker; +EX heptagon deletion_marker; template void subcell(cell *c, const T& t) { if(GOLDBERG) { @@ -269,7 +267,7 @@ template void subcell(cell *c, const T& t) { t(c); } -void clearHexes(heptagon *at) { +EX void clearHexes(heptagon *at) { if(at->c7 && at->cdata) { delete at->cdata; at->cdata = NULL; @@ -288,7 +286,7 @@ void unlink_cdata(heptagon *h) { } } -void clearfrom(heptagon *at) { +EX void clearfrom(heptagon *at) { if(!at) return; queue q; unlink_cdata(at); @@ -332,7 +330,7 @@ void clearfrom(heptagon *at) { //printf("maxq = %d\n", maxq); } -void verifycell(cell *c) { +EX void verifycell(cell *c) { int t = c->type; for(int i=0; imove(i); @@ -346,7 +344,7 @@ void verifycell(cell *c) { } } -void verifycells(heptagon *at) { +EX void verifycells(heptagon *at) { if(GOLDBERG || IRREGULAR || archimedean) return; for(int i=0; itype; i++) if(at->move(i) && at->move(i)->move(at->c.spin(i)) && at->move(i)->move(at->c.spin(i)) != at) { printf("hexmix error %p [%d s=%d] %p %p\n", at, i, at->c.spin(i), at->move(i), at->move(i)->move(at->c.spin(i))); @@ -357,7 +355,7 @@ void verifycells(heptagon *at) { verifycell(at->c7); } -int eudist(int sx, int sy) { +EX int eudist(int sx, int sy) { int z0 = abs(sx); int z1 = abs(sy); if(a4 && BITRUNCATED) @@ -367,12 +365,12 @@ int eudist(int sx, int sy) { return max(max(z0,z1), z2); } -int eudist(int vec) { +EX int eudist(int vec) { auto p = vec_to_pair(vec); return eudist(p.first, p.second); } -int compdist(int dx[]) { +EX int compdist(int dx[]) { int mi = dx[0]; for(int u=0; udists[decodeId(c->master)]; if(nil) return DISTANCE_UNKNOWN; @@ -412,12 +410,13 @@ int celldist(cell *c) { return compdist(dx); } -#define ALTDIST_BOUNDARY 99999 -#define ALTDIST_UNKNOWN 99998 +#if HDR +static const int ALTDIST_BOUNDARY = 99999; +static const int ALTDIST_UNKNOWN = 99998; +static const int ALTDIST_ERROR = 90000; +#endif -#define ALTDIST_ERROR 90000 - -int celldistAlt(cell *c) { +EX int celldistAlt(cell *c) { if(masterless) { if(fulltorus) return celldist(c); if(euwrap) return cylinder_alt(c); @@ -463,20 +462,19 @@ int celldistAlt(cell *c) { return mi; } -int dirfromto(cell *cfrom, cell *cto) { +EX int dirfromto(cell *cfrom, cell *cto) { for(int i=0; itype; i++) if(cfrom->move(i) == cto) return i; return -1; } -#define RPV_MODULO 5 - -#define RPV_RAND 0 -#define RPV_ZEBRA 1 -#define RPV_EMERALD 2 -#define RPV_PALACE 3 -#define RPV_CYCLE 4 - -int getCdata(cell *c, int j); +#if HDR +static const int RPV_MODULO = 5; +static const int RPV_RAND = 0; +static const int RPV_ZEBRA = 1; +static const int RPV_EMERALD = 2; +static const int RPV_PALACE = 3; +static const int RPV_CYCLE = 4; +#endif // x mod 5 = pattern type // x mod (powers of 2) = pattern type specific @@ -484,7 +482,7 @@ int getCdata(cell *c, int j); // x mod 7 = chance of pattern-specific pic // whole = randomization -bool randpattern(cell *c, int rval) { +EX bool randpattern(cell *c, int rval) { int i, sw=0; switch(rval%5) { case 0: @@ -527,7 +525,7 @@ bool randpattern(cell *c, int rval) { return 0; } -string describeRPM(eLand l) { +EX string describeRPM(eLand l) { int rval = randompattern[l]; switch(rval%5) { case 0: @@ -547,7 +545,7 @@ string describeRPM(eLand l) { return "?"; } -int randpatternCode(cell *c, int rval) { +EX int randpatternCode(cell *c, int rval) { switch(rval % RPV_MODULO) { case 1: return zebra40(c); @@ -565,12 +563,12 @@ int randpatternCode(cell *c, int rval) { char rpm_memoize[3][256][RANDITER+1]; -void clearMemoRPM() { +EX void clearMemoRPM() { for(int a=0; a<3; a++) for(int b=0; b<256; b++) for(int i=0; imaster].second; return pair_to_vec(ld_to_int(T[0][GDIM]), ld_to_int((spin(60*degree) * T)[0][GDIM])); } -cdata *arcmCdata(cell *c) { +EX cdata *arcmCdata(cell *c) { heptagon *h2 = arcm::archimedean_gmatrix[c->master].first; dynamicval g(geometry, gNormal); dynamicval cm(currentmap, arcm::current_altmap); return getHeptagonCdata(h2); } -int getCdata(cell *c, int j) { +EX int getCdata(cell *c, int j) { if(masterless) return getEuclidCdata(decodeId(c->master))->val[j]; else if(archimedean && euclid) return getEuclidCdata(pseudocoords(c))->val[j]; @@ -834,7 +832,7 @@ int getCdata(cell *c, int j) { } } -int getBits(cell *c) { +EX int getBits(cell *c) { if(masterless) return getEuclidCdata(decodeId(c->master))->bits; else if(archimedean && euclid) return getEuclidCdata(pseudocoords(c))->bits; @@ -851,7 +849,7 @@ int getBits(cell *c) { } } -cell *heptatdir(cell *c, int d) { +EX cell *heptatdir(cell *c, int d) { if(d&1) { cell *c2 = createMov(c, d); int s = c->c.spin(d); @@ -861,7 +859,7 @@ cell *heptatdir(cell *c, int d) { else return createMov(c, d); } -int heptdistance(heptagon *h1, heptagon *h2) { +EX int heptdistance(heptagon *h1, heptagon *h2) { // very rough distance int d = 0; #if CAP_CRYSTAL @@ -877,7 +875,7 @@ int heptdistance(heptagon *h1, heptagon *h2) { } } -int heptdistance(cell *c1, cell *c2) { +EX int heptdistance(cell *c1, cell *c2) { #if CAP_CRYSTAL if(geometry == gCrystal) return crystal::space_distance(c1, c2); #endif @@ -893,7 +891,7 @@ set dists_computed; int perma_distances; -void compute_saved_distances(cell *c1, int max_range, int climit) { +EX void compute_saved_distances(cell *c1, int max_range, int climit) { celllister cl(c1, max_range, climit, NULL); @@ -901,7 +899,7 @@ void compute_saved_distances(cell *c1, int max_range, int climit) { saved_distances[make_pair(c1, cl.lst[i])] = cl.dists[i]; } -void permanent_long_distances(cell *c1) { +EX void permanent_long_distances(cell *c1) { keep_distances_from.insert(c1); if(racing::on) compute_saved_distances(c1, 300, 1000000); @@ -909,14 +907,14 @@ void permanent_long_distances(cell *c1) { compute_saved_distances(c1, 120, 200000); } -void erase_saved_distances() { +EX void erase_saved_distances() { saved_distances.clear(); dists_computed.clear(); for(auto c: keep_distances_from) compute_saved_distances(c, 120, 200000); perma_distances = isize(saved_distances); } -cell *random_in_distance(cell *c, int d) { +EX cell *random_in_distance(cell *c, int d) { vector choices; for(auto& p: saved_distances) println(hlog, p); @@ -926,7 +924,7 @@ cell *random_in_distance(cell *c, int d) { return choices[hrand(isize(choices))]; } -int celldistance(cell *c1, cell *c2) { +EX int celldistance(cell *c1, cell *c2) { if((masterless) && (euclid6 || (euclid4 && PURE))) { if(!euwrap) @@ -994,7 +992,7 @@ int celldistance(cell *c1, cell *c2) { return hyperbolic_celldistance(c1, c2); } -vector build_shortest_path(cell *c1, cell *c2) { +EX vector build_shortest_path(cell *c1, cell *c2) { #if CAP_CRYSTAL if(geometry == gCrystal) return crystal::build_shortest_path(c1, c2); #endif @@ -1047,7 +1045,7 @@ vector build_shortest_path(cell *c1, cell *c2) { return p; } -void clearCellMemory() { +EX void clearCellMemory() { for(int i=0; i, version " VER "\n"); #if !NOLICENSE @@ -277,9 +277,9 @@ int arg::readCommon() { return 0; } -purehookset hooks_config; +EX purehookset hooks_config; -hookset *hooks_args; +EX hookset *hooks_args; namespace arg { int curphase; diff --git a/config.cpp b/config.cpp index 5d58b809..7c2cced6 100644 --- a/config.cpp +++ b/config.cpp @@ -4,14 +4,14 @@ namespace hr { -ld bounded_mine_percentage = 0.1; -int bounded_mine_quantity, bounded_mine_max; +EX ld bounded_mine_percentage = 0.1; +EX int bounded_mine_quantity, bounded_mine_max; const char *conffile = "hyperrogue.ini"; -array sightranges; +EX array sightranges; -videopar vid; +EX videopar vid; #define DEFAULT_WALLMODE (ISMOBILE ? 3 : 5) #define DEFAULT_MONMODE (ISMOBILE ? 2 : 4) @@ -62,7 +62,7 @@ void hwrite(hstream& hs, const charstyle& cs) { // void hread(hstream& hs, charstyle& cs) { hread_raw(hs, cs); } // void hwrite(hstream& hs, const charstyle& cs) { hwrite_raw(hs, cs); } -string csnameid(int id) { +EX string csnameid(int id) { if(id == 0) return XLAT("male"); if(id == 1) return XLAT("female"); if(id == 2) return XLAT("Prince"); @@ -73,22 +73,22 @@ string csnameid(int id) { return XLAT("none"); } -string csname(charstyle& cs) { +EX string csname(charstyle& cs) { return csnameid(cs.charid); } -int playergender() { +EX int playergender() { return (getcs().charid >= 0 && (getcs().charid&1)) ? GEN_F : GEN_M; } -int princessgender() { +EX int princessgender() { int g = playergender(); if(vid.samegender) return g; return g == GEN_M ? GEN_F : GEN_M; } -int default_language; +EX int default_language; -int lang() { +EX int lang() { if(vid.language >= 0) return vid.language; return default_language; @@ -131,7 +131,7 @@ unsigned int dresscolors2[] = { 7, 0x8080FFC0, 0x80FF80C0, 0xFF8080C0, 0xFFFF80C unsigned int swordcolors[] = { 6, 0xC0C0C0FF, 0xFFFFFFFF, 0xFFC0C0FF, 0xC0C0FFFF, 0x808080FF, 0x202020FF }; unsigned int eyecolors[] = { 4, 0x00C000FF, 0x0000C0FF, 0xC00000FF, 0xC0C000FF, 0x804010FF, 0x00C000FF }; -void initcs(charstyle &cs) { +EX void initcs(charstyle &cs) { cs.charid = 0; cs.skincolor = 0xD0D0D0FF; cs.haircolor = 0x686868FF; @@ -143,12 +143,12 @@ void initcs(charstyle &cs) { cs.lefthanded = false; } -void savecolortable(colortable& ct, string name) { +EX void savecolortable(colortable& ct, string name) { for(int i=0; i rx(vid.xres, 0); dynamicval ry(vid.yres, 0); dynamicval rf(vid.fsize, 0); @@ -577,7 +577,7 @@ void resetConfig() { #endif #if CAP_CONFIG -void saveConfig() { +EX void saveConfig() { DEBB(DF_INIT, ("save config\n")); FILE *f = fopen(conffile, "wt"); if(!f) { @@ -617,7 +617,7 @@ void readf(FILE *f, ld& x) { map > allconfigs; -void parseline(const string& str) { +EX void parseline(const string& str) { if(str[0] == '#') return; for(int i=0; i vid.yres * 1.4 ? sm::SIDE : sm::MAYDARK; gamescreen(0); @@ -933,7 +933,7 @@ void showGraphConfig() { }; } -void switchFullscreen() { +EX void switchFullscreen() { vid.full = !vid.full; #if ISANDROID addMessage(XLAT("Reenter HyperRogue to apply this setting")); @@ -950,7 +950,7 @@ void switchFullscreen() { #endif } -void switchGL() { +EX void switchGL() { vid.usingGL = !vid.usingGL; if(vid.usingGL) addMessage(XLAT("openGL mode enabled")); if(!vid.usingGL) addMessage(XLAT("openGL mode disabled")); @@ -963,9 +963,7 @@ void switchGL() { #endif } -void resetConfigMenu(); - -void edit_whatever(char type, int index) { +EX void edit_whatever(char type, int index) { if(type == 'f') { dialog::editNumber(whatever[index], -10, 10, 1, 0, XLAT("whatever"), "f:" + its(index)); @@ -986,7 +984,7 @@ void edit_whatever(char type, int index) { }; } -void configureOther() { +EX void configureOther() { gamescreen(3); dialog::init(XLAT("other settings")); @@ -1047,7 +1045,7 @@ void configureOther() { dialog::display(); } -void configureInterface() { +EX void configureInterface() { gamescreen(3); dialog::init(XLAT("interface")); @@ -1112,7 +1110,7 @@ void configureInterface() { } #if CAP_SDLJOY -void showJoyConfig() { +EX void showJoyConfig() { gamescreen(4); dialog::init(XLAT("joystick configuration")); @@ -1160,7 +1158,7 @@ void showJoyConfig() { } #endif -void projectionDialog() { +EX void projectionDialog() { vid.tc_alpha = ticks; dialog::editNumber(vid.alpha, -5, 5, .1, 1, XLAT("projection"), @@ -1194,7 +1192,7 @@ void projectionDialog() { }; } -void explain_detail() { +EX void explain_detail() { dialog::addHelp(XLAT( "Objects at distance less than %1 absolute units " "from the center will be displayed with high " @@ -1203,7 +1201,7 @@ void explain_detail() { )); } -void add_edit_fov(char key = 'f') { +EX void add_edit_fov(char key IS('f')) { dialog::addSelItem(XLAT("field of view"), fts(vid.fov) + "°", key); dialog::add_action([] { dialog::editNumber(vid.fov, 1, 170, 1, 45, "field of view", @@ -1217,7 +1215,7 @@ void add_edit_fov(char key = 'f') { }); } -void showStereo() { +EX void showStereo() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(0); dialog::init(XLAT("stereo vision config")); @@ -1287,7 +1285,7 @@ void showStereo() { }; } -void config_camera_rotation() { +EX void config_camera_rotation() { dialog::editNumber(vid.ballangle, 0, 90, 5, 0, XLAT("camera rotation in 3D models"), "Rotate the camera in 3D models (ball model, hyperboloid, and hemisphere). " "Note that hyperboloid and hemisphere models are also available in the " @@ -1298,7 +1296,7 @@ void config_camera_rotation() { ); } -void add_edit_wall_quality(char c) { +EX void add_edit_wall_quality(char c) { dialog::addSelItem(XLAT("wall quality"), its(vid.texture_step), c); dialog::add_action([] { dialog::editNumber(vid.texture_step, 1, 16, 1, 1, XLAT("wall quality"), @@ -1324,7 +1322,7 @@ void add_edit_wall_quality(char c) { }); } -void show3D() { +EX void show3D() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(0); dialog::init(XLAT("3D configuration")); @@ -1608,14 +1606,14 @@ void show3D() { }; } -void switchcolor(unsigned int& c, unsigned int* cs) { +EX void switchcolor(unsigned int& c, unsigned int* cs) { dialog::openColorDialog(c, cs); } double cc_footphase; int lmousex, lmousey; -void showCustomizeChar() { +EX void showCustomizeChar() { cc_footphase += hypot(mousex - lmousex, mousey - lmousey); lmousex = mousex; lmousey = mousey; @@ -1690,7 +1688,7 @@ void showCustomizeChar() { }; } -void refresh_canvas() { +EX void refresh_canvas() { manual_celllister cl; cl.add(cwt.at); @@ -1704,7 +1702,7 @@ void refresh_canvas() { } } -void edit_color_table(colortable& ct, const reaction_t& r = reaction_t()) { +EX void edit_color_table(colortable& ct, const reaction_t& r IS(reaction_t())) { cmode = sm::SIDE; gamescreen(0); dialog::init(XLAT("colors & aura")); @@ -1718,7 +1716,7 @@ void edit_color_table(colortable& ct, const reaction_t& r = reaction_t()) { dialog::display(); } -void show_color_dialog() { +EX void show_color_dialog() { cmode = sm::SIDE | sm::DIALOG_STRICT_X; getcstat = '-'; gamescreen(0); @@ -1825,7 +1823,7 @@ void show_color_dialog() { } #if CAP_CONFIG -void resetConfigMenu() { +EX void resetConfigMenu() { dialog::init(XLAT("reset all configuration")); dialog::addInfo("Are you sure?"); dialog::addItem("yes, and delete the config file", 'd'); @@ -1857,7 +1855,7 @@ void resetConfigMenu() { #endif #if CAP_TRANS -void selectLanguageScreen() { +EX void selectLanguageScreen() { gamescreen(4); dialog::init("select language"); // intentionally not translated @@ -1915,7 +1913,7 @@ void selectLanguageScreen() { } #endif -void configureMouse() { +EX void configureMouse() { gamescreen(1); dialog::init(XLAT("mouse & touchscreen")); @@ -1957,7 +1955,7 @@ void configureMouse() { dialog::display(); } -void showSettings() { +EX void showSettings() { gamescreen(1); dialog::init(XLAT("settings")); @@ -2010,7 +2008,7 @@ void showSettings() { #if CAP_COMMANDLINE -int read_color_args() { +EX int read_color_args() { using namespace arg; if(argis("-back")) { @@ -2049,7 +2047,7 @@ int read_color_args() { return 0; } -int read_config_args() { +EX int read_config_args() { using namespace arg; if(argis("-c")) { PHASE(1); shift(); conffile = argcs(); } @@ -2194,7 +2192,7 @@ int read_config_args() { // mode changes: -int read_gamemode_args() { +EX int read_gamemode_args() { using namespace arg; if(argis("-P")) { diff --git a/control.cpp b/control.cpp index 7fb26315..5a6c04c7 100644 --- a/control.cpp +++ b/control.cpp @@ -6,36 +6,38 @@ namespace hr { int frames; bool outoffocus = false; -int mousex, mousey; -hyperpoint mouseh, mouseoh; +EX int mousex, mousey; +EX hyperpoint mouseh, mouseoh; -bool leftclick, rightclick, targetclick, hiliteclick, anyshiftclick, wheelclick, - forcetarget, lshiftclick, lctrlclick, numlock_on; -bool gtouched; +EX bool leftclick, rightclick, targetclick, hiliteclick, anyshiftclick, wheelclick; +EX bool forcetarget, lshiftclick, lctrlclick, numlock_on; +EX bool gtouched; bool holdmouse; -int getcstat, lgetcstat; ld getcshift; bool inslider; +EX int getcstat, lgetcstat; +ld getcshift; +EX bool inslider; function keyhandler = [] (int sym, int uni) {}; function joyhandler = [] (SDL_Event &ev) {return false;}; // is the player using mouse? (used for auto-cross) -bool mousing = true; +EX bool mousing = true; // is the mouse button pressed? -bool mousepressed = false; -bool mousemoved = false; -bool actonrelease = false; +EX bool mousepressed = false; +EX bool mousemoved = false; +EX bool actonrelease = false; bool mousepan, oldmousepan; #if CAP_MOUSEGRAB -ld mouseaim_x, mouseaim_y; +EX ld mouseaim_x, mouseaim_y; #endif -ld mouseaim_sensitivity = 0.01; +EX ld mouseaim_sensitivity = 0.01; -int timetowait; +EX int timetowait; #if CAP_SDLJOY int joyx, joyy, panjoyx, panjoyy; @@ -45,22 +47,22 @@ movedir joydir; movedir mousedest; ld shiftmul = 1; -cell *mouseover, *mouseover2, *lmouseover; +EX cell *mouseover, *mouseover2, *lmouseover; ld modist, modist2, centdist; int lastt; -bool mouseout() { +EX bool mouseout() { if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true; return outofmap(mouseh); } -bool mouseout2() { +EX bool mouseout2() { if((getcstat && getcstat != '-') || (lgetcstat && lgetcstat != '-')) return true; return outofmap(mouseh) || outofmap(mouseoh); } -movedir vectodir(const hyperpoint& P) { +EX movedir vectodir(const hyperpoint& P) { transmatrix U = ggmatrix(cwt.at); if(GDIM == 3 && WDIM == 2) U = radar_transform * U; @@ -96,11 +98,11 @@ movedir vectodir(const hyperpoint& P) { return res; } -void remission() { +EX void remission() { if(!canmove && (cmode & sm::NORMAL)) showMissionScreen(); } -hyperpoint move_destination_vec(int d) { +EX hyperpoint move_destination_vec(int d) { if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone()); // else if(WDIM == 2 && pmodel == mdPerspective) return cspin(0, 2, d * M_PI/4) * tC0(pushone()); // else if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone()); @@ -108,7 +110,7 @@ hyperpoint move_destination_vec(int d) { else return cspin(0, 2, d * M_PI/4) * tC0(pushone()); } -void movepckeydir(int d) { +EX void movepckeydir(int d) { DEBB(DF_GRAPH, ("movepckeydir\n")); // EUCLIDEAN @@ -119,7 +121,7 @@ void movepckeydir(int d) { if(!canmove) movepcto(md), remission(); else movepcto(md); } -void calcMousedest() { +EX void calcMousedest() { if(mouseout()) return; if(vid.revcontrol == true) { mouseh[0] = -mouseh[0]; mouseh[1] = -mouseh[1]; } ld mousedist = intval(mouseh, tC0(ggmatrix(cwt.at))); @@ -156,7 +158,7 @@ void calcMousedest() { cwt = bcwt; } -void mousemovement() { +EX void mousemovement() { if(DIM == 3) { if(WDIM == 2) { if(View[2][2] < -0.75) @@ -182,7 +184,7 @@ void mousemovement() { SDL_Joystick* sticks[8]; int numsticks; -void initJoysticks() { +EX void initJoysticks() { DEBB(DF_INIT, ("init joysticks")); numsticks = SDL_NumJoysticks(); if(numsticks > 8) numsticks = 8; @@ -197,7 +199,7 @@ void initJoysticks() { } } -void closeJoysticks() { +EX void closeJoysticks() { DEBB(DF_INIT, ("close joysticks")); for(int i=0; i 0) { if(applyCheat(uni, mouseover)) @@ -493,9 +495,9 @@ void handleKeyNormal(int sym, int uni) { if(sym == PSEUDOKEY_MEMORY) pushScreen(show_memory_menu); } -bool need_mouseh = false; +EX bool need_mouseh = false; -void fix_mouseh() { +EX void fix_mouseh() { if(!need_mouseh) ; #if CAP_RUG else if(rug::rugged) @@ -514,7 +516,7 @@ void fix_mouseh() { need_mouseh = false; } -void handlekey(int sym, int uni) { +EX void handlekey(int sym, int uni) { if(callhandlers(false, hooks_handleKey, sym, uni)) return; @@ -522,14 +524,14 @@ void handlekey(int sym, int uni) { } #if !CAP_SDL -void mainloopiter() { printf("(compiled without SDL -- no action)\n"); quitmainloop = true; } +EX void mainloopiter() { printf("(compiled without SDL -- no action)\n"); quitmainloop = true; } #else // Warning: a very long function! todo: refactor int cframelimit = 1000; -void resize_screen_to(int x, int y) { +EX void resize_screen_to(int x, int y) { dual::split_or_do([&] { vid.xres = x; vid.yres = y; @@ -542,7 +544,7 @@ void resize_screen_to(int x, int y) { int lastframe; -void mainloopiter() { +EX void mainloopiter() { DEBB(DF_GRAPH, ("main loop\n")); @@ -697,7 +699,7 @@ void mainloopiter() { fix_mouseh(); } -void handle_event(SDL_Event& ev) { +EX void handle_event(SDL_Event& ev) { bool normal = cmode & sm::NORMAL; Uint8 *keystate = SDL_GetKeyState(NULL); @@ -939,7 +941,7 @@ void handle_event(SDL_Event& ev) { } #endif -void mainloop() { +EX void mainloop() { if(noGUI) return; lastt = 0; #if ISWEB @@ -951,7 +953,7 @@ void mainloop() { } #if ISMOBILE==1 -void displayabutton(int px, int py, string s, int col) { +EX void displayabutton(int px, int py, string s, int col) { // TMP int siz = vid.yres > vid.xres ? vid.fsize*2 : vid.fsize * 3/2; int rad = (int) realradius(); @@ -973,7 +975,7 @@ void displayabutton(int px, int py, string s, int col) { } #endif -bool interpret_as_direction(int sym, int uni) { +EX bool interpret_as_direction(int sym, int uni) { #ifdef FAKE_SDL return false; #else @@ -981,7 +983,7 @@ bool interpret_as_direction(int sym, int uni) { #endif } -int get_direction_key(int sym, int uni) { +EX int get_direction_key(int sym, int uni) { if(interpret_as_direction(sym, uni)) { #ifndef FAKE_SDL if(sym == SDLK_KP1) return SDLK_END; @@ -998,7 +1000,7 @@ int get_direction_key(int sym, int uni) { return sym; } -bool gmodekeys(int sym, int uni) { +EX bool gmodekeys(int sym, int uni) { #if CAP_RUG if(rug::rugged && rug::handlekeys(sym, uni)) return true; #endif @@ -1031,7 +1033,7 @@ bool gmodekeys(int sym, int uni) { } } -bool haveMobileCompass() { +EX bool haveMobileCompass() { #if ISMOBILE if(longclick) return false; #else @@ -1041,7 +1043,7 @@ bool haveMobileCompass() { return canmove && !shmup::on && vid.mobilecompasssize > 0 && isize(screens) == 1; } -bool handleCompass() { +EX bool handleCompass() { if(!haveMobileCompass()) return false; using namespace shmupballs; @@ -1066,7 +1068,7 @@ bool handleCompass() { } // orientation sensitivity -namespace ors { +EX namespace ors { int mode; double sensitivity = 1; @@ -1083,7 +1085,7 @@ transmatrix getOrientation() { } #endif -void reset() { +EX void reset() { #if CAP_ORIENTATION if(mode) last_orientation = getOrientation(); relative_matrix = Id; @@ -1096,7 +1098,7 @@ void delayed_reset() { #endif } -void show() { +EX void show() { #if CAP_ORIENTATION cmode = sm::SIDE | sm::MAYDARK; gamescreen(0); @@ -1189,7 +1191,7 @@ void rerotate(transmatrix& T) { int first_check, last_check; -void check_orientation() { +EX void check_orientation() { #if CAP_ORIENTATION if(!mode) return; @@ -1209,6 +1211,6 @@ void check_orientation() { #endif } -} +EX } } diff --git a/dialogs.cpp b/dialogs.cpp index 3c0b6052..44ff773e 100644 --- a/dialogs.cpp +++ b/dialogs.cpp @@ -18,19 +18,67 @@ namespace hr { const char* COLORBAR = "###"; -namespace dialog { +EX namespace dialog { - color_t dialogcolor = 0xC0C0C0; +#if HDR + static const int DONT_SHOW = 16; - void addBack() { + enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diIntSlider, diSlider, diBigItem, diKeyboard}; + + struct item { + tDialogItem type; + string body; + string value; + string keycaption; + int key; + color_t color, colorv, colork, colors, colorc; + int scale; + double param; + int p1, p2, p3; + int position; + }; + + struct scaler { + ld (*direct) (ld); + ld (*inverse) (ld); + bool positive; + }; + + static inline ld identity_f(ld x) { return x; }; + + const static scaler identity = {identity_f, identity_f, false}; + const static scaler logarithmic = {log, exp, true}; + const static scaler asinhic = {asinh, sinh, false}; + const static scaler asinhic100 = {[] (ld x) { return asinh(x*100); }, [] (ld x) { return sinh(x)/100; }, false}; + + struct numberEditor { + ld *editwhat; + string s; + ld vmin, vmax, step, dft; + string title, help; + scaler sc; + int *intval; ld intbuf; + bool animatable; + }; + + extern numberEditor ne; + + inline void scaleLog() { ne.sc = logarithmic; } + inline void scaleSinh() { ne.sc = asinhic; } + inline void scaleSinh100() { ne.sc = asinhic100; } +#endif + + EX color_t dialogcolor = 0xC0C0C0; + + EX void addBack() { addItem(XLAT("go back"), SDLK_ESCAPE); } - void addHelp() { + EX void addHelp() { addItem(XLAT("help"), SDLK_F1); } - namespace zoom { + EX namespace zoom { int zoomf = 1, shiftx, shifty; bool zoomoff = false; @@ -50,19 +98,19 @@ namespace dialog { void stopzoom() { zoomoff = true; } - bool displayfr(int x, int y, int b, int size, const string &s, color_t color, int align) { + EX bool displayfr(int x, int y, int b, int size, const string &s, color_t color, int align) { return hr::displayfr(x * zoomf + shiftx, y * zoomf + shifty, b, size * zoomf, s, color, align); } - bool displayfr_highlight(int x, int y, int b, int size, const string &s, color_t color, int align, int hicolor) { + EX bool displayfr_highlight(int x, int y, int b, int size, const string &s, color_t color, int align, int hicolor IS(0xFFFF00)) { bool clicked = hr::displayfr(x * zoomf + shiftx, y * zoomf + shifty, b, size * zoomf, s, color, align); if(clicked) hr::displayfr(x * zoomf + shiftx, y * zoomf + shifty, b, size * zoomf, s, hicolor, align); return clicked; } - }; + EX }; #if CAP_MENUSCALING && CAP_SDL - void handleZooming(SDL_Event &ev) { + EX void handleZooming(SDL_Event &ev) { using namespace zoom; if(zoomoff || !(cmode & sm::ZOOMABLE)) { nozoom(); return; @@ -71,38 +119,38 @@ namespace dialog { if(ev.type == SDL_MOUSEBUTTONUP && zoomf > 1) stopzoom(); } #else - inline void handleZooming(SDL_Event &ev) {} + EX void handleZooming(SDL_Event &ev) {} #endif - vector items; + EX vector items; - item& lastItem() { return items[items.size() - 1]; } + EX item& lastItem() { return items[items.size() - 1]; } - map key_actions; + EX map key_actions; - void add_key_action(int key, const reaction_t& action) { + EX void add_key_action(int key, const reaction_t& action) { while(key_actions.count(key)) key++; key_actions[key] = action; } - void add_action(const reaction_t& action) { + EX void add_action(const reaction_t& action) { add_key_action(lastItem().key, action); } - void add_action_push(const reaction_t& action) { add_action([action] { pushScreen(action); }); } + EX void add_action_push(const reaction_t& action) { add_action([action] { pushScreen(action); }); } - void handler(int sym, int uni) { + EX void handler(int sym, int uni) { dialog::handleNavigation(sym, uni); if(doexiton(sym, uni)) popScreen(); }; - void init() { + EX void init() { items.clear(); key_actions.clear(); keyhandler = dialog::handler; } - string keyname(int k) { + EX string keyname(int k) { if(k == 0) return ""; if(k == SDLK_ESCAPE) return "Esc"; if(k == SDLK_F5) return "F5"; @@ -117,7 +165,7 @@ namespace dialog { return "?"; } - void addSlider(double d1, double d2, double d3, int key) { + EX void addSlider(double d1, double d2, double d3, int key) { item it; it.type = diSlider; it.color = dialogcolor; @@ -127,7 +175,7 @@ namespace dialog { items.push_back(it); } - void addIntSlider(int d1, int d2, int d3, int key) { + EX void addIntSlider(int d1, int d2, int d3, int key) { item it; it.type = diIntSlider; it.color = dialogcolor; @@ -138,7 +186,7 @@ namespace dialog { items.push_back(it); } - void addSelItem(string body, string value, int key) { + EX void addSelItem(string body, string value, int key) { item it; it.type = diItem; it.body = body; @@ -156,17 +204,17 @@ namespace dialog { items.push_back(it); } - void addBoolItem(string body, bool value, int key) { + EX void addBoolItem(string body, bool value, int key) { addSelItem(body, ONOFF(value), key); } - int displaycolor(unsigned col) { + EX int displaycolor(unsigned col) { int c = col >> 8; if(!c) return 0x181818; return c; } - void addKeyboardItem(string keys) { + EX void addKeyboardItem(string keys) { item it; it.type = diKeyboard; it.body = keys; @@ -176,7 +224,7 @@ namespace dialog { items.push_back(it); } - void addColorItem(string body, int value, int key) { + EX void addColorItem(string body, int value, int key) { item it; it.type = diItem; it.body = body; @@ -191,7 +239,7 @@ namespace dialog { items.push_back(it); } - void addHelp(string body) { + EX void addHelp(string body) { item it; it.type = diHelp; it.body = body; @@ -202,7 +250,7 @@ namespace dialog { items.push_back(it); } - void addInfo(string body, color_t color) { + EX void addInfo(string body, color_t color IS(dialogcolor)) { item it; it.type = diInfo; it.body = body; @@ -211,7 +259,7 @@ namespace dialog { items.push_back(it); } - void addItem(string body, int key) { + EX void addItem(string body, int key) { item it; it.type = diItem; it.body = body; @@ -225,7 +273,7 @@ namespace dialog { items.push_back(it); } - void addBigItem(string body, int key) { + EX void addBigItem(string body, int key) { item it; it.type = diBigItem; it.body = body; @@ -238,7 +286,7 @@ namespace dialog { items.push_back(it); } - int addBreak(int val) { + EX int addBreak(int val) { item it; it.type = diBreak; it.scale = val; @@ -246,7 +294,7 @@ namespace dialog { return items.size()-1; } - void addTitle(string body, color_t color, int scale) { + EX void addTitle(string body, color_t color, int scale) { item it; it.type = diTitle; it.body = body; @@ -255,17 +303,17 @@ namespace dialog { items.push_back(it); } - void init(string title, color_t color, int scale, int brk) { + EX void init(string title, color_t color IS(0xE8E8E8), int scale IS(150), int brk IS(60)) { init(); addTitle(title, color, scale); addBreak(brk); } - int dcenter, dwidth; + EX int dcenter, dwidth; - int dialogflags; + EX int dialogflags; - int displayLong(string str, int siz, int y, bool measure) { + EX int displayLong(string str, int siz, int y, bool measure) { int last = 0; int lastspace = 0; @@ -298,11 +346,11 @@ namespace dialog { return y; } - int tothei, dialogwidth, dfsize, dfspace, leftwidth, rightwidth, innerwidth, itemx, keyx, valuex; + EX int tothei, dialogwidth, dfsize, dfspace, leftwidth, rightwidth, innerwidth, itemx, keyx, valuex; string highlight_text; - void measure() { + EX void measure() { tothei = 0; dialogwidth = 0; innerwidth = 0; @@ -329,7 +377,7 @@ namespace dialog { valuex = dcenter - fwidth / 2 + leftwidth + innerwidth + dfsize/2; } - void display() { + EX void display() { int N = items.size(); dfsize = vid.fsize; #if ISMOBILE || ISPANDORA @@ -469,7 +517,7 @@ namespace dialog { return it.type == diItem || it.type == diBigItem; } - void handleNavigation(int &sym, int &uni) { + EX void handleNavigation(int &sym, int &uni) { if(uni == '\n' || uni == '\r' || DIRECTIONKEY == SDLK_KP5) for(int i=0; i val) { @@ -727,9 +775,9 @@ namespace dialog { }; } - int numberdark; + EX int numberdark; - void formula_keyboard(bool lr) { + EX void formula_keyboard(bool lr) { addKeyboardItem("1234567890"); addKeyboardItem("=+-*/^()\x3"); addKeyboardItem("qwertyuiop"); @@ -738,7 +786,7 @@ namespace dialog { addKeyboardItem(lr ? " \t\x1\x2" : " \t"); } - void drawNumberDialog() { + EX void drawNumberDialog() { cmode = sm::NUMBER | dialogflags; if(numberdark < DONT_SHOW) gamescreen(numberdark); @@ -834,7 +882,7 @@ namespace dialog { int nlpage = 1; int wheelshift = 0; - int handlePage(int& nl, int& nlm, int perpage) { + EX int handlePage(int& nl, int& nlm, int perpage) { nlm = nl; int onl = nl; int ret = 0; @@ -855,7 +903,7 @@ namespace dialog { return ret; } - void displayPageButtons(int i, bool pages) { + EX void displayPageButtons(int i, bool pages) { int i0 = vid.yres - vid.fsize; int xr = vid.xres / 80; if(pages) if(displayfrZH(xr*8, i0, 1, vid.fsize, IFM("1 - ") + XLAT("page") + " 1", nlpage == 1 ? 0xD8D8C0 : dialogcolor, 8)) @@ -870,7 +918,7 @@ namespace dialog { getcstat = SDLK_F1; } - bool handlePageButtons(int uni) { + EX bool handlePageButtons(int uni) { if(uni == '1') nlpage = 1, wheelshift = 0; else if(uni == '2') nlpage = 2, wheelshift = 0; else if(uni == '3') nlpage = 0, wheelshift = 0; @@ -880,7 +928,7 @@ namespace dialog { return true; } - void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) { + EX void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) { ne.editwhat = &x; ne.s = disp(x); ne.vmin = vmin; @@ -905,13 +953,13 @@ namespace dialog { #endif } - void editNumber(int& x, int vmin, int vmax, ld step, int dft, string title, string help) { + EX void editNumber(int& x, int vmin, int vmax, ld step, int dft, string title, string help) { editNumber(ne.intbuf, vmin, vmax, step, dft, title, help); ne.intbuf = x; ne.intval = &x; ne.s = its(x); ne.animatable = false; } - void helpToEdit(int& x, int vmin, int vmax, int step, int dft) { + EX void helpToEdit(int& x, int vmin, int vmax, int step, int dft) { popScreen(); string title = "help"; if(help[0] == '@') { @@ -944,7 +992,7 @@ namespace dialog { void handleKeyFile(int sym, int uni); - void drawFileDialog() { + EX void drawFileDialog() { displayfr(vid.xres/2, 30 + vid.fsize, 2, vid.fsize, filecaption, forecolor, 8); @@ -998,7 +1046,7 @@ namespace dialog { keyhandler = handleKeyFile; } - void handleKeyFile(int sym, int uni) { + EX void handleKeyFile(int sym, int uni) { string& s(*cfileptr); int i = isize(s) - (editext?0:4); @@ -1041,7 +1089,7 @@ namespace dialog { return; } - void openFileDialog(string& filename, string fcap, string ext, bool_reaction_t action) { + EX void openFileDialog(string& filename, string fcap, string ext, bool_reaction_t action) { cfileptr = &filename; filecaption = fcap; cfileext = ext; @@ -1051,9 +1099,9 @@ namespace dialog { // infix/v/vpush - string infix; + EX string infix; - bool hasInfix(const string &s) { + EX bool hasInfix(const string &s) { if(infix == "") return true; string t = ""; for(int i=0; i= 'A' && uni <= 'Z') infix += uni; else if(uni >= 'a' && uni <= 'z') infix += uni-32; else if(infix != "" && uni == 8) infix = infix.substr(0, isize(infix)-1); @@ -1076,18 +1124,18 @@ namespace dialog { return true; } - vector > v; + EX vector > v; - void vpush(color_t color, const char *name) { + EX void vpush(color_t color, const char *name) { string s = XLATN(name); if(!hasInfix(s)) return; dialog::v.push_back(make_pair(s, color)); } int editpos = 0; - string *edited_string; + EX string *edited_string; - string view_edited_string() { + EX string view_edited_string() { string cs = *edited_string; if(editpos < 0) editpos = 0; if(editpos > isize(cs)) editpos = isize(cs); @@ -1095,17 +1143,17 @@ namespace dialog { return cs; } - void start_editing(string& s) { + EX void start_editing(string& s) { edited_string = &s; editpos = isize(s); } - string editchecker(int sym, int uni) { + EX string editchecker(int sym, int uni) { if(uni >= 32 && uni < 127) return string("") + char(uni); return ""; } - bool handle_edit_string(int sym, int uni, function checker) { + EX bool handle_edit_string(int sym, int uni, function checker IS(editchecker)) { auto& es = *edited_string; string u2; if(DKEY == SDLK_LEFT) editpos--; @@ -1125,7 +1173,7 @@ namespace dialog { return true; } - void string_edit_dialog() { + EX void string_edit_dialog() { cmode = sm::NUMBER | dialogflags; if(numberdark < DONT_SHOW) gamescreen(numberdark); @@ -1155,7 +1203,7 @@ namespace dialog { }; } - void edit_string(string& s, string title, string help) { + EX void edit_string(string& s, string title, string help) { start_editing(s); ne.title = title; ne.help = help; @@ -1168,7 +1216,7 @@ namespace dialog { numberdark = 0; } - void confirm_dialog(const string& text, const reaction_t& act) { + EX void confirm_dialog(const string& text, const reaction_t& act) { gamescreen(1); dialog::addBreak(250); dialog::init(XLAT("WARNING"), 0xFF0000, 150, 100); @@ -1182,15 +1230,38 @@ namespace dialog { dialog::display(); } - void addBoolItem_action(const string& s, bool& b, char c) { + EX void addBoolItem_action(const string& s, bool& b, char c) { dialog::addBoolItem(s, b, c); dialog::add_action([&b] { b = !b; }); } - void addBoolItem_action_neg(const string& s, bool& b, char c) { + EX void addBoolItem_action_neg(const string& s, bool& b, char c) { dialog::addBoolItem(s, !b, c); dialog::add_action([&b] { b = !b; }); } + + #if HDR + + template void addBoolItem_choice(const string& s, T& b, T val, char c) { + addBoolItem(s, b == val, c); + add_action([&b, val] { b = val; }); + } + + inline void cheat_if_confirmed(const reaction_t& act) { + if(needConfirmationEvenIfSaved()) pushScreen([act] () { confirm_dialog(XLAT("This will enable the cheat mode, making this game ineligible for scoring. Are you sure?"), act); }); + else act(); + } + + inline void do_if_confirmed(const reaction_t& act) { + if(needConfirmationEvenIfSaved()) pushScreen([act] () { confirm_dialog(XLAT("This will end your current game and start a new one. Are you sure?"), act); }); + else act(); + } + + inline reaction_t add_confirmation(const reaction_t& act) { + return [act] { do_if_confirmed(act); }; + } + #endif + }; } diff --git a/drawing.cpp b/drawing.cpp index 0aadbab7..95aeb8df 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -5,7 +5,35 @@ namespace hr { -unsigned char& part(color_t& col, int i) { +#if HDR +static const int POLY_DRAWLINES = 1; // draw the lines +static const int POLY_DRAWAREA = 2; // draw the area +static const int POLY_INVERSE = 4; // draw the inverse -- useful in stereographic projection +static const int POLY_ISSIDE = 8; // never draw in inverse +static const int POLY_BEHIND = 16; // there are points behind the camera +static const int POLY_TOOLARGE = 32; // some coordinates are too large -- best not to draw to avoid glitches +static const int POLY_INFRONT = 64; // on the sphere (orthogonal projection), do not draw without any points in front +static const int POLY_HASWALLS = 128; // floor shapes which have their sidewalls +static const int POLY_PLAIN = 256; // plain floors +static const int POLY_FULL = 512; // full floors +static const int POLY_HASSHADOW = 1024; // floor shapes which have their shadows, or can use shFloorShadow +static const int POLY_GP = 2048; // Goldberg shapes +static const int POLY_VCONVEX = 4096; // Convex shape (vertex) +static const int POLY_CCONVEX = 8192; // Convex shape (central) +static const int POLY_CENTERIN = 16384; // new system of side checking +static const int POLY_FORCEWIDE = (1<<15); // force wide lines +static const int POLY_NOTINFRONT = (1<<16); // points not in front +static const int POLY_NIF_ERROR = (1<<17); // points moved to the outline cross the image, disable +static const int POLY_BADCENTERIN = (1<<18); // new system of side checking +static const int POLY_PRECISE_WIDE = (1<<19); // precise width calculation +static const int POLY_FORCE_INVERTED = (1<<20); // force inverted +static const int POLY_ALWAYS_IN = (1<<21); // always draw this +static const int POLY_TRIANGLES = (1<<22); // made of TRIANGLES, not TRIANGLE_FAN +static const int POLY_INTENSE = (1<<23); // extra intense colors +static const int POLY_DEBUG = (1<<24); // debug this shape +#endif + +EX unsigned char& part(color_t& col, int i) { unsigned char* c = (unsigned char*) &col; #if ISMOBILE return c[i]; @@ -20,11 +48,11 @@ unsigned char& part(color_t& col, int i) { bool fatborder; -color_t poly_outline; +EX color_t poly_outline; // #define STLSORT -vector> ptds; +EX vector> ptds; #if CAP_GL color_t text_color; @@ -42,7 +70,7 @@ vector line_vertices; void glapplymatrix(const transmatrix& V); #endif -void glflush() { +EX void glflush() { #if MINIMIZE_GL_CALLS if(isize(triangle_vertices)) { // printf("%08X %08X | %d shapes, %d/%d vertices\n", triangle_color, line_color, shapes_merged, isize(triangle_vertices), isize(line_vertices)); @@ -104,7 +132,7 @@ SDL_Surface *aux; #if CAP_POLY #define POLYMAX 60000 -vector glcoords; +EX vector glcoords; #endif @@ -142,7 +170,7 @@ bool knowgood; hyperpoint goodpoint; vector> tofix; -bool two_sided_model() { +EX bool two_sided_model() { if(DIM == 3) return false; if(pmodel == mdHyperboloid) return !euclid; // if(pmodel == mdHemisphere) return true; @@ -153,7 +181,7 @@ bool two_sided_model() { return false; } -int get_side(const hyperpoint& H) { +EX int get_side(const hyperpoint& H) { if(pmodel == mdDisk && sphere) { double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2]; double horizon = curnorm / vid.alpha; @@ -176,7 +204,7 @@ int get_side(const hyperpoint& H) { return 0; } -bool correct_side(const hyperpoint& H) { +EX bool correct_side(const hyperpoint& H) { return get_side(H) == spherespecial; } @@ -435,7 +463,7 @@ void glapplymatrix(const transmatrix& V) { glhr::set_modelview(glhr::as_glmatrix(mat)); } -int global_projection; +EX int global_projection; #if MAXMDIM >= 4 extern renderbuffer *floor_textures; @@ -555,7 +583,7 @@ void dqi_poly::gldraw() { } #endif -ld scale_at(const transmatrix& T) { +EX ld scale_at(const transmatrix& T) { if(DIM == 3 && pmodel == mdPerspective) return 1 / abs((tC0(T))[2]); if(sol) return 1; hyperpoint h1, h2, h3; @@ -565,7 +593,7 @@ ld scale_at(const transmatrix& T) { return sqrt(hypot_d(2, h2-h1) * hypot_d(2, h3-h1) / .0001); } -ld linewidthat(const hyperpoint& h) { +EX ld linewidthat(const hyperpoint& h) { if(!(vid.antialias & AA_LINEWIDTH)) return 1; else if(hyperbolic && pmodel == mdDisk && vid.alpha == 1 && !ISWEB) { double dz = h[DIM]; @@ -585,7 +613,7 @@ ld linewidthat(const hyperpoint& h) { return 1; } -void set_width(ld w) { +EX void set_width(ld w) { #if MINIMIZE_GL_CALLS if(w != glhr::current_linewidth) glflush(); #endif @@ -1111,11 +1139,11 @@ void dqi_poly::draw() { vector prettylinepoints; -void prettypoint(const hyperpoint& h) { +EX void prettypoint(const hyperpoint& h) { prettylinepoints.push_back(glhr::pointtogl(h)); } -void prettylinesub(const hyperpoint& h1, const hyperpoint& h2, int lev) { +EX void prettylinesub(const hyperpoint& h1, const hyperpoint& h2, int lev) { if(lev >= 0) { hyperpoint h3 = midz(h1, h2); prettylinesub(h1, h3, lev-1); @@ -1124,7 +1152,7 @@ void prettylinesub(const hyperpoint& h1, const hyperpoint& h2, int lev) { else prettypoint(h2); } -void prettyline(hyperpoint h1, hyperpoint h2, color_t col, int lev, int flags, PPR prio) { +EX void prettyline(hyperpoint h1, hyperpoint h2, color_t col, int lev, int flags, PPR prio) { prettylinepoints.clear(); prettypoint(h1); prettylinesub(h1, h2, lev); @@ -1144,7 +1172,7 @@ void prettyline(hyperpoint h1, hyperpoint h2, color_t col, int lev, int flags, P ptd.draw(); } -void prettypoly(const vector& t, color_t fillcol, color_t linecol, int lev) { +EX void prettypoly(const vector& t, color_t fillcol, color_t linecol, int lev) { prettylinepoints.clear(); prettypoint(t[0]); for(int i=0; i curvedata; int curvestart = 0; bool keep_curvedata = false; -void queuereset(eModel m, PPR prio) { +EX void queuereset(eModel m, PPR prio) { queueaction(prio, [m] () { glflush(); pmodel = m; }); } @@ -1203,12 +1231,12 @@ void dqi_circle::draw() { drawCircle(x, y, size, color, fillcolor); } -void initquickqueue() { +EX void initquickqueue() { ptds.clear(); poly_outline = OUTLINE_NONE; } -void sortquickqueue() { +EX void sortquickqueue() { for(int i=1; iprio < ptds[i-1]->prio) { swap(ptds[i], ptds[i-1]); @@ -1217,7 +1245,7 @@ void sortquickqueue() { else i++; } -void quickqueue() { +EX void quickqueue() { spherespecial = 0; reset_projection(); current_display->set_all(0); int siz = isize(ptds); @@ -1264,7 +1292,7 @@ void dqi_line::draw_back() { draw(); } -void sort_drawqueue() { +EX void sort_drawqueue() { for(int a=0; a dv (pmodel, mdHyperboloidFlat); for(auto& ptd: ptds) @@ -1348,12 +1376,12 @@ void draw_backside() { extern bool lshiftclick, lctrlclick; -void reverse_transparent_walls() { +EX void reverse_transparent_walls() { int pt = int(PPR::TRANSPARENT_WALL); reverse(&ptds[qp0[pt]], &ptds[qp[pt]]); } -void draw_main() { +EX void draw_main() { if(sphere && DIM == 3 && pmodel == mdPerspective) { for(int p: {1, 0, 2, 3}) { if(elliptic && p < 2) continue; @@ -1402,7 +1430,7 @@ void draw_main() { } -void drawqueue() { +EX void drawqueue() { callhooks(hook_drawqueue); reset_projection(); // reset_projection() is not sufficient here, because we need to know shaderside_projection @@ -1501,7 +1529,7 @@ template T& queuea(PPR prio, U... u) { } #if CAP_SHAPES -dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, PPR prio) { +EX dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, PPR prio) { if(prio == PPR::DEFAULT) prio = h.prio; auto& ptd = queuea (prio); @@ -1540,7 +1568,7 @@ void addfloats(vector& v, hyperpoint h) { for(int i=0; i<3; i++) v.push_back(h[i]); } -dqi_poly& queuetable(const transmatrix& V, const vector& f, int cnt, color_t linecol, color_t fillcol, PPR prio) { +EX dqi_poly& queuetable(const transmatrix& V, const vector& f, int cnt, color_t linecol, color_t fillcol, PPR prio) { auto& ptd = queuea (prio); @@ -1559,7 +1587,7 @@ dqi_poly& queuetable(const transmatrix& V, const vector& f, int cnt, c } #if CAP_SHAPES -dqi_poly& queuepoly(const transmatrix& V, const hpcshape& h, color_t col) { +EX dqi_poly& queuepoly(const transmatrix& V, const hpcshape& h, color_t col) { return queuepolyat(V,h,col,h.prio); } @@ -1568,22 +1596,22 @@ void queuepolyb(const transmatrix& V, const hpcshape& h, color_t col, int b) { } #endif -void curvepoint(const hyperpoint& H1) { +EX void curvepoint(const hyperpoint& H1) { curvedata.push_back(glhr::pointtogl(H1)); } -dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio) { +EX dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio) { auto &res = queuetable(Id, curvedata, isize(curvedata)-curvestart, linecol, fillcol, prio); res.offset = curvestart; curvestart = isize(curvedata); return res; } -dqi_action& queueaction(PPR prio, const reaction_t& action) { +EX dqi_action& queueaction(PPR prio, const reaction_t& action) { return queuea (prio, action); } -dqi_line& queueline(const hyperpoint& H1, const hyperpoint& H2, color_t col, int prf, PPR prio) { +EX dqi_line& queueline(const hyperpoint& H1, const hyperpoint& H2, color_t col, int prf IS(0), PPR prio IS(PPR::LINE)) { auto& ptd = queuea (prio); ptd.H1 = H1; @@ -1596,7 +1624,7 @@ dqi_line& queueline(const hyperpoint& H1, const hyperpoint& H2, color_t col, int return ptd; } -void queuestr(int x, int y, int shift, int size, string str, color_t col, int frame, int align) { +EX void queuestr(int x, int y, int shift, int size, string str, color_t col, int frame IS(0), int align IS(8)) { auto& ptd = queuea (PPR::TEXT); ptd.x = x; ptd.y = y; @@ -1608,7 +1636,7 @@ void queuestr(int x, int y, int shift, int size, string str, color_t col, int fr ptd.frame = frame ? ((poly_outline & ~ 255)+frame) : 0; } -void queuechr(int x, int y, int shift, int size, char chr, color_t col, int frame, int align) { +EX void queuechr(int x, int y, int shift, int size, char chr, color_t col, int frame IS(0), int align IS(8)) { auto& ptd = queuea (PPR::TEXT); ptd.x = x; ptd.y = y; @@ -1620,7 +1648,7 @@ void queuechr(int x, int y, int shift, int size, char chr, color_t col, int fram ptd.frame = frame ? (poly_outline & ~ 255) : 0; } -void queuecircle(int x, int y, int size, color_t color, PPR prio, color_t fillcolor) { +EX void queuecircle(int x, int y, int size, color_t color, PPR prio IS(PPR::CIRCLE), color_t fillcolor IS(0)) { auto& ptd = queuea(prio); ptd.x = x; ptd.y = y; @@ -1630,7 +1658,7 @@ void queuecircle(int x, int y, int size, color_t color, PPR prio, color_t fillco ptd.linewidth = vid.linewidth; } -void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) { +EX void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) { hyperpoint hscr; applymodel(h, hscr); xc = current_display->xcenter + current_display->radius * hscr[0]; @@ -1639,49 +1667,49 @@ void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) { // EYETODO sc = vid.eye * current_display->radius * hscr[2]; } -ld scale_in_pixels(const transmatrix& V) { +EX ld scale_in_pixels(const transmatrix& V) { return scale_at(V) * cgi.scalefactor * current_display->radius / 2.5; } -bool getcoord0_checked(const hyperpoint& h, int& xc, int &yc, int &zc) { +EX bool getcoord0_checked(const hyperpoint& h, int& xc, int &yc, int &zc) { if(invalid_point(h)) return false; if(point_behind(h)) return false; getcoord0(h, xc, yc, zc); return true; } -void queuechr(const hyperpoint& h, int size, char chr, color_t col, int frame) { +EX void queuechr(const hyperpoint& h, int size, char chr, color_t col, int frame IS(0)) { int xc, yc, sc; if(getcoord0_checked(h, xc, yc, sc)) queuechr(xc, yc, sc, size, chr, col, frame); } -void queuechr(const transmatrix& V, double size, char chr, color_t col, int frame) { +EX void queuechr(const transmatrix& V, double size, char chr, color_t col, int frame IS(0)) { int xc, yc, sc; if(getcoord0_checked(tC0(V), xc, yc, sc)) queuechr(xc, yc, sc, scale_in_pixels(V) * size, chr, col, frame); } -void queuestr(const hyperpoint& h, int size, const string& chr, color_t col, int frame) { +EX void queuestr(const hyperpoint& h, int size, const string& chr, color_t col, int frame IS(0)) { int xc, yc, sc; if(getcoord0_checked(h, xc, yc, sc)) queuestr(xc, yc, sc, size, chr, col, frame); } -void queuestr(const transmatrix& V, double size, const string& chr, color_t col, int frame, int align) { +EX void queuestr(const transmatrix& V, double size, const string& chr, color_t col, int frame IS(0), int align IS(8)) { int xc, yc, sc; if(getcoord0_checked(tC0(V), xc, yc, sc)) queuestr(xc, yc, sc, scale_in_pixels(V) * size, chr, col, frame, align); } -void queuecircle(const transmatrix& V, double size, color_t col) { +EX void queuecircle(const transmatrix& V, double size, color_t col) { int xc, yc, sc; if(!getcoord0_checked(tC0(V), xc, yc, sc)) return; int xs, ys, ss; getcoord0(V * xpush0(.01), xs, ys, ss); queuecircle(xc, yc, scale_in_pixels(V) * size, col); } -void queuemarkerat(const transmatrix& V, color_t col) { +EX void queuemarkerat(const transmatrix& V, color_t col) { #if CAP_SHAPES queuepolyat(V, cgi.shTriangle, col, PPR::LINE); #endif diff --git a/euclid.cpp b/euclid.cpp index d0bd74d3..48329d07 100644 --- a/euclid.cpp +++ b/euclid.cpp @@ -10,13 +10,13 @@ namespace hr { // NOTE: patterns assume that pair_to_vec(0,1) % 3 == 2! // Thus, pair_to_vec(0,1) must not be e.g. a power of four -int cell_to_vec(cell *c); +EX int cell_to_vec(cell *c); -int pair_to_vec(int x, int y) { +EX int pair_to_vec(int x, int y) { return x + (y << 15); } -pair vec_to_pair(int vec) { +EX pair vec_to_pair(int vec) { int x = vec & ((1<<15)-1); int y = (vec >> 15); if(x >= (1<<14)) x -= (1<<15), y++; @@ -468,13 +468,13 @@ int cellwalker_to_vec(cellwalker cw) { return torusconfig::id_to_vec(id, cw.mirrored); } -int cell_to_vec(cell *c) { +EX int cell_to_vec(cell *c) { int id = decodeId(c->master); if(!fulltorus) return id; return torusconfig::id_to_vec(id, false); } -pair cell_to_pair(cell *c) { +EX pair cell_to_pair(cell *c) { return vec_to_pair(cell_to_vec(c)); } @@ -483,12 +483,12 @@ union heptacoder { int id; }; -int decodeId(heptagon* h) { +EX int decodeId(heptagon* h) { heptacoder u; u.h = h; return u.id; } -heptagon* encodeId(int id) { +EX heptagon* encodeId(int id) { heptacoder u; u.id = id; return u.h; @@ -1157,7 +1157,7 @@ namespace euclid3 { #endif -ld matrixnorm(const transmatrix& Mat) { +EX ld matrixnorm(const transmatrix& Mat) { return Mat[0][DIM] * Mat[0][DIM] + Mat[1][DIM] * Mat[1][DIM] + Mat[2][DIM] * Mat[2][DIM]; } diff --git a/expansion.cpp b/expansion.cpp index 316c093f..e31ad72c 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -905,7 +905,7 @@ int sibling_distance(cell *a, cell *b, int limit) { } } -int hyperbolic_celldistance(cell *c1, cell *c2) { +EX int hyperbolic_celldistance(cell *c1, cell *c2) { int found_distance = INF; int d = 0, d1 = celldist0(c1), d2 = celldist0(c2), sl_used = 0; diff --git a/game.cpp b/game.cpp index 080d1dfb..6c37da4d 100644 --- a/game.cpp +++ b/game.cpp @@ -5,14 +5,14 @@ namespace hr { -int lastsafety; -int mutantphase; -int turncount; +EX int lastsafety; +EX int mutantphase; +EX int turncount; int rosewave, rosephase; int avengers, mirrorspirits, wandering_jiangshi, jiangshi_on_screen; -int gamerange_bonus = 0; -int gamerange() { return getDistLimit() + gamerange_bonus; } +EX int gamerange_bonus = 0; +EX int gamerange() { return getDistLimit() + gamerange_bonus; } cell *lastmove; eLastmovetype lastmovetype, nextmovetype; @@ -64,9 +64,9 @@ flagtype havewhat, hadwhat; bool seenSevenMines = false; -bool pureHardcore() { return hardcore && hardcoreAt < PUREHARDCORE_LEVEL; } +EX bool pureHardcore() { return hardcore && hardcoreAt < PUREHARDCORE_LEVEL; } -bool canmove = true; +EX bool canmove = true; int sagephase = 0; @@ -96,19 +96,19 @@ bool landvisited[landtypes]; bool eq(short a, short b) { return a==b; } // game state -array items; -array kills; +EX array items; +EX array kills; int explore[10], exploreland[10][landtypes], landcount[landtypes]; map > hiitems; bool orbused[ittypes], lastorbused[ittypes]; -bool playermoved = true; // center on the PC? +EX bool playermoved = true; // center on the PC? bool flipplayer = true; // flip the player image after move, do not flip after attack -int cheater = 0; // did the player cheat? +EX int cheater = 0; // did the player cheat? int anthraxBonus = 0; // for using Safety in tactical Camelot -vector dcal; // queue for cpdist +EX vector dcal; // queue for cpdist vector pathq; // queue for pathdist vector offscreen; // offscreen cells to take care off @@ -136,8 +136,8 @@ int first7; // the position of the first monster at distance 7 in dcal cellwalker cwt; // single player character position -inline cell*& singlepos() { return cwt.at; } -inline bool singleused() { return !(shmup::on || multi::players > 1); } +EX inline cell*& singlepos() { return cwt.at; } +EX inline bool singleused() { return !(shmup::on || multi::players > 1); } // the main random number generator for the game // all the random calls related to the game mechanics (land generation, AI...) should use hrngen @@ -146,16 +146,19 @@ inline bool singleused() { return !(shmup::on || multi::players > 1); } std::mt19937 hrngen; -void shrand(int i) { +EX void shrand(int i) { hrngen.seed(i); } -int hrandpos() { return hrngen() & HRANDMAX; } +EX int hrandpos() { return hrngen() & HRANDMAX; } // using our own implementations rather than ones from , // to make sure that they return the same values on different compilers -int hrand(int i) { +// a random integer from [0..i), generated by the game's main generator +// we want the same world to be generated if the seed is the same. For this purpose, +// hrand should be used for all the game-related generation, and nowhere else +EX int hrand(int i) { unsigned d = hrngen() - hrngen.min(); long long m = (long long) (hrngen.max() - hrngen.min()) + 1; m /= i; @@ -164,16 +167,16 @@ int hrand(int i) { return hrand(i); } -ld hrandf() { +EX ld hrandf() { return (hrngen() - hrngen.min()) / (hrngen.max() + 1.0 - hrngen.min()); } -int hrandstate() { +EX int hrandstate() { std::mt19937 r2 = hrngen; return r2() & HRANDMAX; } -void initcell(cell *c) { +EX void initcell(cell *c) { c->mpdist = INFD; // minimum distance from the player, ever c->cpdist = INFD; // current distance from the player c->pathdist = PINFD;// current distance from the player, along paths (used by yetis) @@ -191,7 +194,7 @@ void initcell(cell *c) { c->monmirror = 0; } -bool doesnotFall(cell *c) { +EX bool doesnotFall(cell *c) { if(c->wall == waChasm) return false; else if(cellUnstable(c) && !in_gravity_zone(c)) { fallingFloorAnimation(c); @@ -201,80 +204,80 @@ bool doesnotFall(cell *c) { return true; } -bool doesFall(cell *c) { return !doesnotFall(c); } +EX bool doesFall(cell *c) { return !doesnotFall(c); } -bool doesFallSound(cell *c) { +EX bool doesFallSound(cell *c) { if(c->land != laMotion && c->land != laZebra) playSound(c, "trapdoor"); return !doesnotFall(c); } -bool itemHidden(cell *c) { +EX bool itemHidden(cell *c) { return isWatery(c) && !(shmup::on && shmup::boatAt(c)); } -bool playerInWater() { +EX bool playerInWater() { for(int i=0; i 1) return multi::player[i].at; return singlepos(); } -bool allPlayersInBoats() { +EX bool allPlayersInBoats() { for(int i=0; iwall != waBoat) return true; return false; } -int whichPlayerOn(cell *c) { +EX int whichPlayerOn(cell *c) { if(singleused()) return c == singlepos() ? 0 : -1; for(int i=0; i= 0; } -bool isPlayerInBoatOn(cell *c, int i) { +EX bool isPlayerInBoatOn(cell *c, int i) { return (playerpos(i) == c && ( c->wall == waBoat || c->wall == waStrandedBoat || (shmup::on && shmup::playerInBoat(i)) )); } -bool playerInBoat(int i) { +EX bool playerInBoat(int i) { return isPlayerInBoatOn(playerpos(i), i); } -bool isPlayerInBoatOn(cell *c) { +EX bool isPlayerInBoatOn(cell *c) { for(int i=0; iwall == waBoat) placeWater(c, c2); if(strandedToo && c->wall == waStrandedBoat) c->wall = waNone; shmup::destroyBoats(c); } -bool playerInPower() { +EX bool playerInPower() { if(singleused()) return singlepos()->land == laPower || singlepos()->land == laHalloween; for(int i=0; iland; return treasureType(lastland); } -void countLocalTreasure() { +EX void countLocalTreasure() { eItem i = localTreasureType(); currentLocalTreasure = i ? items[i] : 0; if(i != itHyperstone) for(int i=0; i mg) @@ -379,13 +382,13 @@ int* killtable[] = { NULL }; -int tkills() { +EX int tkills() { int res = 0; for(int i=0; killtable[i]; i++) res += killtable[i][0]; return res; } -int killtypes() { +EX int killtypes() { int res = 0; for(int i=0; killtable[i]; i++) if(killtable[i][0]) res++; return res; @@ -397,7 +400,7 @@ bool bird_disruption(cell *c) { return c->cpdist <= 5 && items[itOrbGravity]; } -bool in_gravity_zone(cell *c) { +EX bool in_gravity_zone(cell *c) { return gravity_state && c->cpdist <= 5; } @@ -452,11 +455,11 @@ eGravity get_move_gravity(cell *c, cell *c2) { } } -bool isWarped(cell *c) { +EX bool isWarped(cell *c) { return isWarpedType(c->land) || (!inmirrororwall(c->land) && (items[itOrb37] && c->cpdist <= 4)); } -bool nonAdjacent(cell *c, cell *c2) { +EX bool nonAdjacent(cell *c, cell *c2) { if(isWarped(c) && isWarped(c2) && warptype(c) == warptype(c2)) { /* int i = neighborId(c, c2); cell *c3 = c->modmove(i+1), *c4 = c->modmove(i-1); @@ -467,11 +470,11 @@ bool nonAdjacent(cell *c, cell *c2) { return false; } -bool nonAdjacentPlayer(cell *c, cell *c2) { +EX bool nonAdjacentPlayer(cell *c, cell *c2) { return nonAdjacent(c, c2) && !markOrb(itOrb37); } -bool thruVine(cell *c, cell *c2) { +EX bool thruVine(cell *c, cell *c2) { return (cellHalfvine(c) && c2->wall == c->wall && c2 != c); // ((c->wall == waFloorC || c->wall == waFloorD) && c2->wall == c->wall && !c2->item && !c->item); } @@ -479,7 +482,7 @@ bool thruVine(cell *c, cell *c2) { // === MOVEMENT FUNCTIONS === // w = from->move(d) -bool againstCurrent(cell *w, cell *from) { +EX bool againstCurrent(cell *w, cell *from) { if(from->land != laWhirlpool) return false; if(againstWind(from, w)) return false; // wind is stronger than current if(!eubinary && (!from->master->alt || !w->master->alt)) return false; @@ -496,7 +499,7 @@ bool againstCurrent(cell *w, cell *from) { return false; } -bool boatGoesThrough(cell *c) { +EX bool boatGoesThrough(cell *c) { if(isGravityLand(c->land)) return false; return (c->wall == waNone && c->land != laMotion && c->land != laZebra && c->land != laReptile) || @@ -508,7 +511,7 @@ bool boatGoesThrough(cell *c) { c->wall == waArrowTrap; } -void placeWater(cell *c, cell *c2) { +EX void placeWater(cell *c, cell *c2) { destroyTrapsOn(c); if(isWatery(c)) ; else if(c2 && isAlchAny(c2)) @@ -521,13 +524,13 @@ void placeWater(cell *c, cell *c2) { if(c->item == itBarrow) c->item = itNone; } -int incline(cell *cfrom, cell *cto) { +EX int incline(cell *cfrom, cell *cto) { return snakelevel(cto) - snakelevel(cfrom); } #define F(x) checkflags(flags,x) -bool checkflags(flagtype flags, int x) { +EX bool checkflags(flagtype flags, int x) { if(flags & x) return true; if(flags & P_ISPLAYER) { if((x & P_WINTER) && markOrb(itOrbWinter)) return true; @@ -542,19 +545,19 @@ bool checkflags(flagtype flags, int x) { return false; } -bool strictlyAgainstGravity(cell *w, cell *from, bool revdir, flagtype flags) { +EX bool strictlyAgainstGravity(cell *w, cell *from, bool revdir, flagtype flags) { return cellEdgeUnstable(w, flags) && cellEdgeUnstable(from, flags) && !(shmup::on && from == w) && gravityLevelDiff(from, w) != (revdir?-1:1) * gravity_zone_diff(from); } -bool anti_alchemy(cell *w, cell *from) { +EX bool anti_alchemy(cell *w, cell *from) { bool alch1 = w->wall == waFloorA && from && from->wall == waFloorB && !w->item && !from->item; alch1 |= w->wall == waFloorB && from && from->wall == waFloorA && !w->item && !from->item; return alch1; } -bool passable(cell *w, cell *from, flagtype flags) { +EX bool passable(cell *w, cell *from, flagtype flags) { bool revdir = (flags&P_REVDIR); bool vrevdir = revdir ^ bool(flags&P_VOID); @@ -702,7 +705,7 @@ bool passable(cell *w, cell *from, flagtype flags) { vector > airmap; -int airdist(cell *c) { +EX int airdist(cell *c) { if(!(havewhat & HF_AIR)) return 3; vector >::iterator it = lower_bound(airmap.begin(), airmap.end(), make_pair(c,0)); @@ -710,7 +713,7 @@ int airdist(cell *c) { return 3; } -ld calcAirdir(cell *c) { +EX ld calcAirdir(cell *c) { if(!c || c->monst == moAirElemental || !passable(c, NULL, P_BLOW)) return 0; for(int i=0; itype; i++) { @@ -734,7 +737,7 @@ ld calcAirdir(cell *c) { return 0; } -bool againstWind(cell *cto, cell *cfrom) { +EX bool againstWind(cell *cto, cell *cfrom) { if(!cfrom || !cto) return false; int dcto = airdist(cto), dcfrom = airdist(cfrom); if(dcto < dcfrom) return true; @@ -825,20 +828,20 @@ bool sharkpassable(cell *w, cell *c) { return true; } -bool canPushStatueOn(cell *c) { +EX bool canPushStatueOn(cell *c) { return passable(c, NULL, P_MONSTER) && !snakelevel(c) && !isWorm(c->monst) && !isReptile(c->wall) && !peace::on && !among(c->wall, waBoat, waFireTrap, waArrowTrap); } -void moveBoat(cell *to, cell *from, int direction_hint) { +EX void moveBoat(cell *to, cell *from, int direction_hint) { eWall x = to->wall; to->wall = from->wall; from->wall = x; to->mondir = neighborId(to, from); moveItem(from, to, false); animateMovement(from, to, LAYER_BOAT, direction_hint); } -void moveBoatIfUsingOne(cell *to, cell *from, int direction_hint) { +EX void moveBoatIfUsingOne(cell *to, cell *from, int direction_hint) { if(from->wall == waBoat && isWatery(to)) moveBoat(to, from, direction_hint); else if(from->wall == waBoat && boatGoesThrough(to) && isFriendly(to) && markEmpathy(itOrbWater)) { placeWater(to, from); @@ -870,18 +873,18 @@ bool againstMagnet(cell *c1, cell *c2, eMonster m) { // (from, to) return false; } -bool againstPair(cell *c1, cell *c2, eMonster m) { // (from, to) +EX bool againstPair(cell *c1, cell *c2, eMonster m) { // (from, to) if(c1->monst == m && !isNeighbor(c2, c1->move(c1->mondir))) return true; return false; } -bool notNearItem(cell *c) { +EX bool notNearItem(cell *c) { forCellCM(c2, c) if(c2->item) return false; return true; } -bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) { +EX bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) { if(w->monst && !(extra & P_MONSTER) && !isPlayerOn(w)) return false; if(m == moWolf) { @@ -972,9 +975,9 @@ bool passable_for(eMonster m, cell *w, cell *from, flagtype extra) { return false; } -eMonster movegroup(eMonster m) { return minf[m].mgroup; } +EX eMonster movegroup(eMonster m) { return minf[m].mgroup; } -void useup(cell *c) { +EX void useup(cell *c) { c->wparam--; if(c->wparam == 0) { drawParticles(c, c->wall == waFire ? 0xC00000 : winf[c->wall].color, 10, 50); @@ -987,7 +990,7 @@ void useup(cell *c) { } } -int realstuntime(cell *c) { +EX int realstuntime(cell *c) { if(isMutantIvy(c)) return (c->stuntime - mutantphase) & 15; return c->stuntime; } @@ -995,7 +998,7 @@ int realstuntime(cell *c) { bool childbug = false; // is w killed if killed is killed? -bool isChild(cell *w, cell *killed) { +EX bool isChild(cell *w, cell *killed) { if(isAnyIvy(w->monst)) { int lim = 0; // printf("w = %p mondir = %d **\n", w, w->mondir); @@ -1016,7 +1019,7 @@ bool isChild(cell *w, cell *killed) { return w == killed; } -bool logical_adjacent(cell *c1, eMonster m1, cell *c2) { +EX bool logical_adjacent(cell *c1, eMonster m1, cell *c2) { if(!c1 || !c2) return true; // cannot really check eMonster m2 = c2->monst; if(!isNeighbor(c1, c2)) @@ -1030,11 +1033,11 @@ bool logical_adjacent(cell *c1, eMonster m1, cell *c2) { return true; } -bool arrow_stuns(eMonster m) { +EX bool arrow_stuns(eMonster m) { return among(m, moCrusher, moMonk, moAltDemon, moHexDemon, moGreater, moGreaterM, moHedge); } -bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) { +EX bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) { // cannot eat worms if((flags & AF_EAT) && isWorm(m2)) return false; @@ -1185,17 +1188,17 @@ bool stalemate::isKilled(cell *w) { return false; }; -bool isNeighbor(cell *c1, cell *c2) { +EX bool isNeighbor(cell *c1, cell *c2) { for(int i=0; itype; i++) if(c1->move(i) == c2) return true; return false; } -bool isNeighborCM(cell *c1, cell *c2) { +EX bool isNeighborCM(cell *c1, cell *c2) { for(int i=0; itype; i++) if(createMov(c1, i) == c2) return true; return false; } -int neighborId(cell *ofWhat, cell *whichOne) { +EX int neighborId(cell *ofWhat, cell *whichOne) { for(int i=0; itype; i++) if(ofWhat->move(i) == whichOne) return i; return -1; } @@ -1203,7 +1206,7 @@ int neighborId(cell *ofWhat, cell *whichOne) { // how many monsters are near eMonster who_kills_me; -bool flashWouldKill(cell *c, flagtype extra) { +EX bool flashWouldKill(cell *c, flagtype extra) { for(int t=0; ttype; t++) { cell *c2 = c->move(t); for(int u=0; utype; u++) { @@ -1219,7 +1222,7 @@ bool flashWouldKill(cell *c, flagtype extra) { return false; } -vector gun_targets(cell *c) { +EX vector gun_targets(cell *c) { manual_celllister cl; vector dists; cl.add(c); dists.push_back(0); @@ -1259,19 +1262,19 @@ bool onboat(stalemate1& sm) { return (c->wall == waBoat) || (cf->wall == waBoat && c->wall == waSea); } -bool krakensafe(cell *c) { +EX bool krakensafe(cell *c) { return items[itOrbFish] || items[itOrbAether] || (c->item == itOrbFish && c->wall == waBoat) || (c->item == itOrbAether && c->wall == waBoat); } -eMonster active_switch() { +EX eMonster active_switch() { return eMonster(passive_switch ^ moSwitch1 ^ moSwitch2); } vector crush_now, crush_next; -bool monstersnear(stalemate1& sm) { +EX bool monstersnear(stalemate1& sm) { cell *c = sm.moveto; bool eaten = false; @@ -1367,11 +1370,11 @@ bool monstersnear(stalemate1& sm) { namespace multi { bool aftermove; } -bool monstersnear2(); +EX bool monstersnear2(); int lastkills; -bool multimove() { +EX bool multimove() { if(multi::cpid == 0) lastkills = tkills(); if(!multi::playerActive(multi::cpid)) return !monstersnear2(); cellwalker bcwt = cwt; @@ -1391,7 +1394,7 @@ bool multimove() { namespace multi { bool checkonly = false; } -bool swordConflict(const stalemate1& sm1, const stalemate1& sm2) { +EX bool swordConflict(const stalemate1& sm1, const stalemate1& sm2) { if(items[itOrbSword] || items[itOrbSword2]) for(int b=0; b<2; b++) if(sm1.comefrom == sm2.swordlast[b] || sm1.comefrom == sm2.swordtransit[b] || sm1.comefrom == sm2.swordnext[b]) @@ -1400,7 +1403,7 @@ bool swordConflict(const stalemate1& sm1, const stalemate1& sm2) { return false; } -bool monstersnear2() { +EX bool monstersnear2() { multi::cpid++; bool b = false; bool recorduse[ittypes]; @@ -1449,7 +1452,7 @@ bool monstersnear2() { return b; } -bool monstersnear(cell *c, cell *nocount, eMonster who, cell *pushto, cell *comefrom) { +EX bool monstersnear(cell *c, cell *nocount, eMonster who, cell *pushto, cell *comefrom) { if(peace::on) return 0; // you are safe @@ -1513,7 +1516,7 @@ bool monstersnear(cell *c, cell *nocount, eMonster who, cell *pushto, cell *come return b; } -bool petrify(cell *c, eWall walltype, eMonster m) { +EX bool petrify(cell *c, eWall walltype, eMonster m) { destroyHalfvine(c); destroyTrapsOn(c); playSound(c, "die-troll"); @@ -1553,7 +1556,7 @@ bool petrify(cell *c, eWall walltype, eMonster m) { return true; } -void killIvy(cell *c, eMonster who) { +EX void killIvy(cell *c, eMonster who) { if(c->monst == moIvyDead) return; if(checkOrb(who, itOrbStone)) petrify(c, waPetrified, c->monst); c->monst = moIvyDead; // NEWYEARFIX @@ -1562,7 +1565,7 @@ void killIvy(cell *c, eMonster who) { killIvy(c->move(i), who); } -void prespill(cell* c, eWall t, int rad, cell *from) { +EX void prespill(cell* c, eWall t, int rad, cell *from) { if(againstWind(c, from)) return; // these monsters block spilling if(c->monst == moSeep || c->monst == moVineSpirit || c->monst == moShark || @@ -1640,17 +1643,17 @@ void prespill(cell* c, eWall t, int rad, cell *from) { prespill(c->move(i), t, rad-1, c); } -void spillfix(cell* c, eWall t, int rad) { +EX void spillfix(cell* c, eWall t, int rad) { if(c->wall == waTemporary) c->wall = t; if(rad) for(int i=0; itype; i++) if(c->move(i)) spillfix(c->move(i), t, rad-1); } -void spill(cell* c, eWall t, int rad) { +EX void spill(cell* c, eWall t, int rad) { prespill(c,t,rad, c); spillfix(c,t,rad); } -void degradeDemons() { +EX void degradeDemons() { addMessage(XLAT("You feel more experienced in demon fighting!")); int dcs = isize(dcal); for(int i=0; imonst) return false; if(c->wall == waDeadwall) { c->wall = waDeadfloor; return true; } if(c->wall == waDune) { c->wall = waNone; return true; } @@ -1706,7 +1707,7 @@ bool earthFloor(cell *c) { return false; } -bool earthWall(cell *c) { +EX bool earthWall(cell *c) { if(c->wall == waDeadfloor || c->wall == waDeadfloor2 || c->wall == waEarthD) { c->item = itNone; c->wall = waDeadwall; @@ -1769,7 +1770,7 @@ bool earthWall(cell *c) { return false; } -bool snakepile(cell *c, eMonster m) { +EX bool snakepile(cell *c, eMonster m) { if(c->wall == waSea && c->land == laOcean) { c->land = laBrownian, c->landparam = 0; } @@ -1836,7 +1837,7 @@ bool snakepile(cell *c, eMonster m) { return true; } -bool makeflame(cell *c, int timeout, bool checkonly) { +EX bool makeflame(cell *c, int timeout, bool checkonly) { if(!checkonly) destroyTrapsOn(c); if(itemBurns(c->item)) { if(checkonly) return true; @@ -1910,7 +1911,7 @@ bool makeflame(cell *c, int timeout, bool checkonly) { return true; } -void explosion(cell *c, int power, int central) { +EX void explosion(cell *c, int power, int central) { playSound(c, "explosion"); drawFireParticles(c, 30, 150); @@ -1950,7 +1951,7 @@ void explosion(cell *c, int power, int central) { } } -void explodeMine(cell *c) { +EX void explodeMine(cell *c) { if(c->wall != waMineMine) return; @@ -1959,7 +1960,7 @@ void explodeMine(cell *c) { auto_teleport_charges(); } -void explodeBarrel(cell *c) { +EX void explodeBarrel(cell *c) { if(c->wall != waExplosiveBarrel) return; @@ -1967,14 +1968,14 @@ void explodeBarrel(cell *c) { explosion(c, 20, 20); } -bool mayExplodeMine(cell *c, eMonster who) { +EX bool mayExplodeMine(cell *c, eMonster who) { if(c->wall != waMineMine) return false; if(ignoresPlates(who)) return false; explodeMine(c); return true; } -void stunMonster(cell *c2, eMonster killer, flagtype flags) { +EX void stunMonster(cell *c2, eMonster killer, flagtype flags) { int newtime = ( c2->monst == moFatGuard ? 2 : c2->monst == moSkeleton && c2->land != laPalace && c2->land != laHalloween ? 7 : @@ -2005,7 +2006,7 @@ void stunMonster(cell *c2, eMonster killer, flagtype flags) { checkStunKill(c2); } -bool attackJustStuns(cell *c2, flagtype f, eMonster attacker) { +EX bool attackJustStuns(cell *c2, flagtype f, eMonster attacker) { if(f & AF_HORNS) return hornStuns(c2); else if(attacker == moArrowTrap && arrow_stuns(c2->monst)) @@ -2018,9 +2019,7 @@ bool attackJustStuns(cell *c2, flagtype f, eMonster attacker) { return isStunnable(c2->monst) && c2->hitpoints > 1; } -void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint); - -void flameHalfvine(cell *c, int val) { +EX void flameHalfvine(cell *c, int val) { if(itemBurns(c->item)) { addMessage(XLAT("%The1 burns!", c->item)); c->item = itNone; @@ -2029,7 +2028,7 @@ void flameHalfvine(cell *c, int val) { c->wparam = val; } -void minerEffect(cell *c) { +EX void minerEffect(cell *c) { eWall ow = c->wall; if(c->wall == waOpenGate || c->wall == waFrozenLake || c->wall == waBoat || c->wall == waStrandedBoat || @@ -2051,7 +2050,7 @@ void minerEffect(cell *c) { if(c->wall != ow && ow) drawParticles(c, winf[ow].color, 16); } -void killMutantIvy(cell *c, eMonster who) { +EX void killMutantIvy(cell *c, eMonster who) { if(checkOrb(who, itOrbStone)) petrify(c, waPetrified, moMutant); removeIvy(c); for(int i=0; itype; i++) @@ -2059,7 +2058,7 @@ void killMutantIvy(cell *c, eMonster who) { killMutantIvy(c->move(i), who); } -void killMonster(cell *c, eMonster who, flagtype deathflags) { +EX void killMonster(cell *c, eMonster who, flagtype deathflags IS(0)) { eMonster m = c->monst; DEBBI(DF_TURN, ("killmonster ", dnameof(m))); @@ -2405,7 +2404,7 @@ void killMonster(cell *c, eMonster who, flagtype deathflags) { } } -void fightmessage(eMonster victim, eMonster attacker, bool stun, flagtype flags) { +EX void fightmessage(eMonster victim, eMonster attacker, bool stun, flagtype flags) { if(isBird(attacker)) { playSound(NULL, "hit-axe"+pick123()); @@ -2507,16 +2506,16 @@ void fightmessage(eMonster victim, eMonster attacker, bool stun, flagtype flags) } } -void fallMonster(cell *c, flagtype flags) { +EX void fallMonster(cell *c, flagtype flags) { attackMonster(c, flags, moNone); } -bool notthateasy(eMonster m) { +EX bool notthateasy(eMonster m) { return isMultitile(m) || isStunnable(m) || m == moDraugr; } -bool attackMonster(cell *c, flagtype flags, eMonster killer) { +EX bool attackMonster(cell *c, flagtype flags, eMonster killer) { if((flags & AF_GETPLAYER) && isPlayerOn(c)) { killThePlayerAt(killer, c, flags); @@ -2594,7 +2593,7 @@ bool attackMonster(cell *c, flagtype flags, eMonster killer) { return ntk > tk; } -void pushMonster(cell *ct, cell *cf, int direction_hint) { +EX void pushMonster(cell *ct, cell *cf, int direction_hint) { moveMonster(ct, cf, direction_hint); if(ct->monst == moBrownBug) { int t = snakelevel(ct) - snakelevel(cf); @@ -2604,7 +2603,7 @@ void pushMonster(cell *ct, cell *cf, int direction_hint) { if(isBull(ct->monst)) ct->monst = moRagingBull; } -bool destroyHalfvine(cell *c, eWall newwall, int tval) { +EX bool destroyHalfvine(cell *c, eWall newwall IS(waNone), int tval IS(6)) { if(cellHalfvine(c)) { for(int t=0; ttype; t++) if(c->move(t)->wall == c->wall) { if(newwall == waPartialFire) flameHalfvine(c->move(t), tval); @@ -2618,9 +2617,9 @@ bool destroyHalfvine(cell *c, eWall newwall, int tval) { return false; } -int coastvalEdge(cell *c) { return coastval(c, laIvoryTower); } +EX int coastvalEdge(cell *c) { return coastval(c, laIvoryTower); } -int gravityLevel(cell *c) { +EX int gravityLevel(cell *c) { if(c->land == laIvoryTower || c->land == laEndorian) return coastval(c, laIvoryTower); if(c->land == laDungeon) @@ -2630,7 +2629,7 @@ int gravityLevel(cell *c) { return 0; } -int gravityLevelDiff(cell *c, cell *d) { +EX int gravityLevelDiff(cell *c, cell *d) { if(c->land != laWestWall || d->land != laWestWall) return gravityLevel(c) - gravityLevel(d); @@ -2648,13 +2647,13 @@ int gravityLevelDiff(cell *c, cell *d) { return 0; } -bool canUnstable(eWall w, flagtype flags) { +EX bool canUnstable(eWall w, flagtype flags) { return w == waNone || w == waCanopy || w == waOpenPlate || w == waClosePlate || w == waOpenGate || ((flags & MF_STUNNED) && (w == waLadder || w == waTrunk || w == waSolidBranch || w == waWeakBranch || w == waBigBush || w == waSmallBush)); } -bool cellEdgeUnstable(cell *c, flagtype flags) { +EX bool cellEdgeUnstable(cell *c, flagtype flags IS(0)) { if(!isGravityLand(c->land) || !canUnstable(c->wall, flags)) return false; if(shmup::on && c->land == laWestWall) return false; forCellEx(c2, c) { @@ -2677,11 +2676,11 @@ bool cellEdgeUnstable(cell *c, flagtype flags) { } // find worms and ivies -void settemp(cell *c) { +EX void settemp(cell *c) { temps.push_back(c); tempval.push_back(c->monst); c->monst = moNone; } -void findWormIvy(cell *c) { +EX void findWormIvy(cell *c) { while(true) { if(c->monst == moWorm || c->monst == moTentacle || c->monst == moWormwait || c->monst == moTentaclewait || c->monst == moTentacleEscaping) { @@ -2737,7 +2736,7 @@ int tidalphase; int tidalsize, tide[200]; -void calcTidalPhase() { +EX void calcTidalPhase() { if(!tidalsize) { for(int i=0; i<5; i++) tide[tidalsize++] = 1; @@ -2769,7 +2768,7 @@ void calcTidalPhase() { tidalphase = 5 + tidalphase / 6; } -int tidespeed() { +EX int tidespeed() { return tide[(turncount+6) % tidalsize] - tidalphase; } @@ -2780,13 +2779,13 @@ bool recalcTide; #define CHAOSPARAM LHU.bytes[2] #if CAP_FIELD -int lavatide(cell *c, int t) { +EX int lavatide(cell *c, int t) { int tc = (shmup::on ? shmup::curtime/400 : turncount); return (windmap::at(c) + (tc+t)*4) & 255; } #endif -void checkTide(cell *c) { +EX void checkTide(cell *c) { if(c->land == laOcean) { int t = c->landparam; @@ -2836,7 +2835,7 @@ void checkTide(cell *c) { #endif } -void buildAirmap() { +EX void buildAirmap() { for(int k=0; k rosemap; // 2 - wave phase 1 // 3 - wave phase 2 -int rosedist(cell *c) { +EX int rosedist(cell *c) { if(!(havewhat&HF_ROSE)) return 0; int&r (rosemap[c]); if((r&7) == 7) return 0; @@ -2867,19 +2866,19 @@ int rosedist(cell *c) { return 0; } -bool againstRose(cell *cfrom, cell *cto) { +EX bool againstRose(cell *cfrom, cell *cto) { if(rosedist(cfrom) != 1) return false; if(cto && rosedist(cto) == 2) return false; return true; } -bool withRose(cell *cfrom, cell *cto) { +EX bool withRose(cell *cfrom, cell *cto) { if(rosedist(cfrom) != 1) return false; if(rosedist(cto) != 2) return false; return true; } -void buildRosemap() { +EX void buildRosemap() { rosephase++; rosephase &= 7; @@ -2916,9 +2915,9 @@ void buildRosemap() { } -int getDistLimit() { return cgi.base_distlimit; } +EX int getDistLimit() { return cgi.base_distlimit; } -bool nogoSlow(cell *to, cell *from) { +EX bool nogoSlow(cell *to, cell *from) { if(cellEdgeUnstable(to) && gravityLevelDiff(to, from) >= 0) return true; if(cellUnstable(to)) return true; return false; @@ -2928,18 +2927,18 @@ bool nogoSlow(cell *to, cell *from) { cell *pd_from; int pd_range; -void onpath(cell *c, int d) { +EX void onpath(cell *c, int d) { c->pathdist = d; pathq.push_back(c); } -void onpath(cell *c, int d, int sp) { +EX void onpath(cell *c, int d, int sp) { c->pathdist = d; pathq.push_back(c); reachedfrom.push_back(sp); } -void clear_pathdata() { +EX void clear_pathdata() { for(auto c: pathq) c->pathdist = PINFD; pathq.clear(); pathqm.clear(); @@ -2948,7 +2947,7 @@ void clear_pathdata() { int pathlock = 0; -void compute_graphical_distance() { +EX void compute_graphical_distance() { if(pathlock) { printf("path error: compute_graphical_distance\n"); } cell *c1 = centerover.at ? centerover.at : pd_from ? pd_from : cwt.at; int sr = get_sightrange_ambush(); @@ -2970,7 +2969,7 @@ void compute_graphical_distance() { } } -void computePathdist(eMonster param) { +EX void computePathdist(eMonster param) { for(cell *c: targets) onpath(c, isPlayerOn(c) ? 0 : 1, hrand(c->type)); @@ -3019,7 +3018,7 @@ void computePathdist(eMonster param) { vector > butterflies; -void addButterfly(cell *c) { +EX void addButterfly(cell *c) { for(int i=0; imonst != moPrincess) { if(isAnyIvy(c->monst)) killMonster(c, moPlayer, 0); @@ -3345,7 +3344,7 @@ bool makeEmpty(cell *c) { int numgates = 0; -void toggleGates(cell *c, eWall type, int rad) { +EX void toggleGates(cell *c, eWall type, int rad) { if(!c) return; celllister cl(c, rad, 1000000, NULL); for(cell *ct: cl.lst) { @@ -3371,7 +3370,7 @@ void toggleGates(cell *c, eWall type, int rad) { } } -void toggleGates(cell *ct, eWall type) { +EX void toggleGates(cell *ct, eWall type) { playSound(ct, "click"); numgates = 0; if(type == waClosePlate && PURE) @@ -3384,15 +3383,15 @@ void toggleGates(cell *ct, eWall type) { playSound(ct, "opengate"); } -void destroyTrapsOn(cell *c) { +EX void destroyTrapsOn(cell *c) { if(c->wall == waArrowTrap) c->wall = waNone, destroyTrapsAround(c); } -void destroyTrapsAround(cell *c) { +EX void destroyTrapsAround(cell *c) { forCellEx(c2, c) destroyTrapsOn(c2); } -void destroyWeakBranch(cell *cf, cell *ct, eMonster who) { +EX void destroyWeakBranch(cell *cf, cell *ct, eMonster who) { if(cf && ct && cf->wall == waWeakBranch && cellEdgeUnstable(ct) && gravityLevelDiff(ct, cf) >= 0 && !ignoresPlates(who)) { cf->wall = waCanopy; @@ -3409,14 +3408,14 @@ void destroyWeakBranch(cell *cf, cell *ct, eMonster who) { } } -bool isCentralTrap(cell *c) { +EX bool isCentralTrap(cell *c) { if(c->wall != waArrowTrap) return false; int i = 0; forCellEx(c2, c) if(c2->wall == waArrowTrap) i++; return i == 2; } -array traplimits(cell *c) { +EX array traplimits(cell *c) { array res; int q = 0; res[2] = c; @@ -3434,7 +3433,7 @@ array traplimits(cell *c) { return res; } -void activateArrowTrap(cell *c) { +EX void activateArrowTrap(cell *c) { if(c->wall == waArrowTrap && c->wparam == 0) { playSound(c, "click"); c->wparam = shmup::on ? 2 : 1; @@ -3448,7 +3447,7 @@ void activateArrowTrap(cell *c) { // this is called from moveMonster, or separately from moveIvy/moveWorm, // or when a dead bird falls (then m == moDeadBird) -void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) { +EX void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) { if(cf) destroyWeakBranch(cf, ct, m); @@ -3490,12 +3489,12 @@ void moveEffect(cell *ct, cell *cf, eMonster m, int direction_hint) { } } -void updateHi(eItem it, int v) { +EX void updateHi(eItem it, int v) { if(!yendor::on) if(v > hiitems[modecode()][it]) hiitems[modecode()][it] = v; } -void gainItem(eItem it) { +EX void gainItem(eItem it) { int g = gold(); items[it]++; if(it != itLotus) updateHi(it, items[it]); if(it == itRevolver && items[it] > 6) items[it] = 6; @@ -3506,11 +3505,11 @@ void gainItem(eItem it) { #endif } -string itemcounter(int qty) { +EX string itemcounter(int qty) { string s = ""; s += " ("; s += its(qty); s += ")"; return s; } -void gainShard(cell *c2, const char *msg) { +EX void gainShard(cell *c2, const char *msg) { invismove = false; string s = XLAT(msg); if(is_mirrorland(c2) && !peace::on) { @@ -3523,7 +3522,7 @@ void gainShard(cell *c2, const char *msg) { invismove = false; } -void uncoverMinesFull(cell *c2) { +EX void uncoverMinesFull(cell *c2) { int mineradius = bounded ? 3 : (items[itBombEgg] < 1 && !tactic::on) ? 0 : @@ -3541,7 +3540,7 @@ void uncoverMinesFull(cell *c2) { } } -void playerMoveEffects(cell *c1, cell *c2) { +EX void playerMoveEffects(cell *c1, cell *c2) { if(peace::on) items[itOrbSword] = c2->land == laBurial ? 100 : 0; @@ -3585,7 +3584,7 @@ void playerMoveEffects(cell *c1, cell *c2) { } } -void beastcrash(cell *c, cell *beast) { +EX void beastcrash(cell *c, cell *beast) { if(c->wall == waPetrified || c->wall == waDeadTroll || c->wall == waDeadTroll2 || c->wall == waGargoyle) { addMessage(XLAT("%The1 crashes into %the2!", beast->monst, c->wall)); @@ -3617,7 +3616,7 @@ void beastcrash(cell *c, cell *beast) { } } -void stayEffect(cell *c) { +EX void stayEffect(cell *c) { eMonster m = c->monst; if(m == moAirElemental) airmap.push_back(make_pair(c, 0)); if(m == moRagingBull && c->mondir != NODIR) { @@ -3630,13 +3629,13 @@ void stayEffect(cell *c) { } } -void makeTrollFootprints(cell *c) { +EX void makeTrollFootprints(cell *c) { if(c->land != laTrollheim) return; if(c->item == itTrollEgg && c->landparam) return; c->landparam = turncount + 100; } -void moveMonster(cell *ct, cell *cf, int direction_hint) { +EX void moveMonster(cell *ct, cell *cf, int direction_hint) { eMonster m = cf->monst; bool fri = isFriendly(cf); if(isDragon(m)) { @@ -3841,17 +3840,17 @@ void moveMonster(cell *ct, cell *cf, int direction_hint) { } } -bool cannotGo(eMonster m, cell *c) { +EX bool cannotGo(eMonster m, cell *c) { if(m == moCrystalSage && (c->land != laCocytus || HEAT(c) > SAGEMELT || allPlayersInBoats())) return true; return false; } -bool wantsToStay(eMonster m) { +EX bool wantsToStay(eMonster m) { return m == moCrystalSage && allPlayersInBoats(); } -bool batsAfraid(cell *c) { +EX bool batsAfraid(cell *c) { // bats for(int i=-1; it/2) dd -= t; @@ -3878,41 +3877,41 @@ int angledist(int t, int d1, int d2) { return dd; } -int angledistButterfly(int t, int d1, int d2) { +EX int angledistButterfly(int t, int d1, int d2) { int dd = d1 - d2; while(dd<0) dd += t; return dd; } -int angledist(cell *c, int d1, int d2) { +EX int angledist(cell *c, int d1, int d2) { return angledist(c->type, d1, d2); } -bool anglestraight(cell *c, int d1, int d2) { +EX bool anglestraight(cell *c, int d1, int d2) { return angledist(c->type, d1, d2) >= c->type / 2; } -int bulldist(cell *c) { +EX int bulldist(cell *c) { int low = 0; forCellEx(c2, c) if(c2->cpdist < c->cpdist) low++; return 8 * c->cpdist - low; } -int bulldistance(cell *c, cell *d) { +EX int bulldistance(cell *c, cell *d) { int low = 0; int cd = celldistance(c, d); forCellEx(c2, c) if(celldistance(c2, d) < cd) low++; return 8 * cd - low; } -int landheattype(cell *c) { +EX int landheattype(cell *c) { if(isIcyLand(c)) return 0; if(c->land == laVolcano) return 2; return 1; } // move value -int moveval(cell *c1, cell *c2, int d, flagtype mf) { +EX int moveval(cell *c1, cell *c2, int d, flagtype mf) { if(!c2) return -5000; eMonster m = c1->monst; @@ -4035,7 +4034,7 @@ int moveval(cell *c1, cell *c2, int d, flagtype mf) { } // stay value -int stayval(cell *c, flagtype mf) { +EX int stayval(cell *c, flagtype mf) { if(isShark(c->monst) && !isWatery(c)) return 525; if(againstRose(c, NULL) && !ignoresSmell(c->monst)) return -1500; @@ -4061,7 +4060,7 @@ int stayval(cell *c, flagtype mf) { return 1000; } -int totalbulldistance(cell *c, int k) { +EX int totalbulldistance(cell *c, int k) { shpos.resize(SHSIZE); int tbd = 0; for(int p=0; p1; k++) { @@ -4086,7 +4085,7 @@ void determinizeBull(cell *c, int *posdir, int& nc) { } } -int determinizeBullPush(cellwalker bull) { +EX int determinizeBullPush(cellwalker bull) { int nc = 2; int dirs[2], positive; bull += wstep; @@ -4102,7 +4101,7 @@ int determinizeBullPush(cellwalker bull) { int posdir[MAX_EDGE], nc; -int pickMoveDirection(cell *c, flagtype mf) { +EX int pickMoveDirection(cell *c, flagtype mf) { int bestval = stayval(c, mf); nc = 1; posdir[0] = -1; @@ -4122,7 +4121,7 @@ int pickMoveDirection(cell *c, flagtype mf) { return posdir[hrand(nc)]; } -int pickDownDirection(cell *c, flagtype mf) { +EX int pickDownDirection(cell *c, flagtype mf) { int downs[MAX_EDGE], qdowns = 0; int bestdif = -100; forCellIdEx(c2, i, c) { @@ -4143,7 +4142,7 @@ int pickDownDirection(cell *c, flagtype mf) { return downs[hrand(qdowns)]; } -vector reverse_directions(cell *c, int dir) { +EX vector reverse_directions(cell *c, int dir) { int d = c->degree(); switch(geometry) { case gBinary3: @@ -4230,7 +4229,7 @@ cell *determinePush(cellwalker who, cell *c2, int subdir, const T& valid, int& p // Angry Beast attack // note: this is done both before and after movement -void beastAttack(cell *c, bool player) { +EX void beastAttack(cell *c, bool player) { if(c->mondir == NODIR) return; forCellIdEx(c2, d, c) { bool opposite = anglestraight(c, d, c->mondir); @@ -4270,7 +4269,7 @@ void beastAttack(cell *c, bool player) { bool quantum; -cell *moveNormal(cell *c, flagtype mf) { +EX cell *moveNormal(cell *c, flagtype mf) { eMonster m = c->monst; if(isPowerMonster(m) && !playerInPower()) return NULL; @@ -4355,7 +4354,7 @@ cell *moveNormal(cell *c, flagtype mf) { } // for sandworms -void explodeAround(cell *c) { +EX void explodeAround(cell *c) { for(int j=0; jtype; j++) { cell* c2 = c->move(j); if(c2) { @@ -4397,7 +4396,7 @@ void explodeAround(cell *c) { } } -void killHardcorePlayer(int id, flagtype flags) { +EX void killHardcorePlayer(int id, flagtype flags) { charstyle& cs = getcs(id); cell *c = playerpos(id); if(flags & AF_FALL) @@ -4425,7 +4424,7 @@ void killHardcorePlayer(int id, flagtype flags) { } } -void killThePlayer(eMonster m, int id, flagtype flags) { +EX void killThePlayer(eMonster m, int id, flagtype flags) { if(markOrb(itOrbShield)) return; if(shmup::on) { multi::cpid = id; @@ -4457,13 +4456,13 @@ void killThePlayer(eMonster m, int id, flagtype flags) { } } -void killThePlayerAt(eMonster m, cell *c, flagtype flags) { +EX void killThePlayerAt(eMonster m, cell *c, flagtype flags) { for(int i=0; i 1) { multi::player[id].at = c; multi::player[id].spin = spin; @@ -4487,7 +4486,7 @@ void mountmove(cell *c, int spin, bool fp, int id) { afterplayermoved(); } -void mountmove(cell *c, int spin, bool fp, cell *ppos) { +EX void mountmove(cell *c, int spin, bool fp, cell *ppos) { for(int i=0; imondir, c->monmirror); // check the mirroring status @@ -4674,7 +4673,7 @@ void ivynext(cell *c) { } // this removes Ivy, but also potentially causes Vines to grow -void removeIvy(cell *c) { +EX void removeIvy(cell *c) { eMonster m = c->monst; c->monst = moNone; // NEWYEARFIX for(int i=0; itype; i++) @@ -4690,7 +4689,7 @@ void removeIvy(cell *c) { } } -void moveivy() { +EX void moveivy() { if(isize(ivies) == 0) return; if(racing::on) return; pathdata pd(moIvyRoot); @@ -4750,7 +4749,7 @@ void moveivy() { } } -bool earthMove(cell *from, int dir) { +EX bool earthMove(cell *from, int dir) { bool b = false; cell *c2 = from->move(dir); int d = from->c.spin(dir); @@ -4766,14 +4765,14 @@ vector gendfs; int targetcount; -bool isTargetOrAdjacent(cell *c) { +EX bool isTargetOrAdjacent(cell *c) { for(int i=0; ipathdist == 0) return; @@ -4869,7 +4868,7 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) { if(isize(gendfs) < 1000 || c->cpdist <= 6) gendfs.push_back(c); } -void groupmove(eMonster movtype, flagtype mf) { +EX void groupmove(eMonster movtype, flagtype mf) { pathdata pd(0); gendfs.clear(); @@ -4931,7 +4930,7 @@ void groupmove(eMonster movtype, flagtype mf) { vector hexdfs; // note: move from 'c' to 'from'! -void moveHexSnake(cell *from, cell *c, int d, bool mounted) { +EX void moveHexSnake(cell *from, cell *c, int d, bool mounted) { if(from->wall == waBoat) from->wall = waSea; moveEffect(from, c, c->monst, revhint(from, d)); from->monst = c->monst; from->mondir = d; from->hitpoints = c->hitpoints; @@ -4952,7 +4951,7 @@ void moveHexSnake(cell *from, cell *c, int d, bool mounted) { else break; } -void snakeAttack(cell *c, bool mounted) { +EX void snakeAttack(cell *c, bool mounted) { for(int j=0; jtype; j++) if(c->move(j) && canAttack(c, moHexSnake, c->move(j), c->move(j)->monst, mounted ? AF_ONLY_ENEMY : (AF_ONLY_FBUG | AF_GETPLAYER))) { @@ -4962,16 +4961,16 @@ void snakeAttack(cell *c, bool mounted) { } } -bool goodmount(cell *c, bool mounted) { +EX bool goodmount(cell *c, bool mounted) { if(mounted) return isMounted(c); else return !isMounted(c); } -int inpair(cell *c, int colorpair) { +EX int inpair(cell *c, int colorpair) { return (colorpair >> pattern_threecolor(c)) & 1; } -int snake_pair(cell *c) { +EX int snake_pair(cell *c) { if(c->mondir == NODIR) return (1 << pattern_threecolor(c)); else @@ -4979,7 +4978,7 @@ int snake_pair(cell *c) { } // note: move from 'c' to 'from'! -void hexvisit(cell *c, cell *from, int d, bool mounted, int colorpair) { +EX void hexvisit(cell *c, cell *from, int d, bool mounted, int colorpair) { if(!c) return; if(cellUnstable(c) || cellEdgeUnstable(c)) return; if(c->pathdist == 0) return; @@ -5014,7 +5013,7 @@ void hexvisit(cell *c, cell *from, int d, bool mounted, int colorpair) { hexdfs.push_back(c); } -void movehex(bool mounted, int colorpair) { +EX void movehex(bool mounted, int colorpair) { pathdata pd(3); hexdfs.clear(); @@ -5044,7 +5043,7 @@ void movehex(bool mounted, int colorpair) { } } -void movehex_rest(bool mounted) { +EX void movehex_rest(bool mounted) { for(int i=0; i young; for(cell *c: currentmap->allcells()) if(c->monst == moMutant && c->stuntime == mutantphase) @@ -5117,15 +5116,15 @@ void movemutant() { __typeof(shpos) shpos; int cshpos = 0; -cell *lastmountpos[MAXPLAYER]; +EX cell *lastmountpos[MAXPLAYER]; -void clearshadow() { +EX void clearshadow() { shpos.resize(SHSIZE); for(int i=0; imonst && isGhostable(victim)) { c->monst = moFriendlyGhost, c->stuntime = 0; @@ -5224,7 +5223,7 @@ void produceGhost(cell *c, eMonster victim, eMonster who) { } } -bool swordAttack(cell *mt, eMonster who, cell *c, int bb) { +EX bool swordAttack(cell *mt, eMonster who, cell *c, int bb) { eMonster m = c->monst; if(c->wall == waCavewall) markOrb(bb ? itOrbSword2: itOrbSword); if(c->wall == waSmallTree || c->wall == waBigTree || c->wall == waRose || c->wall == waCTree || c->wall == waVinePlant || @@ -5261,17 +5260,17 @@ bool swordAttack(cell *mt, eMonster who, cell *c, int bb) { return false; } -void swordAttackStatic(int bb) { +EX void swordAttackStatic(int bb) { swordAttack(cwt.at, moPlayer, sword::pos(multi::cpid, bb), bb); } -void swordAttackStatic() { +EX void swordAttackStatic() { for(int bb = 0; bb < 2; bb++) if(sword::orbcount(bb)) swordAttackStatic(bb); } -void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) { +EX void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) { if(!items[orb]) return; if(who != moPlayer && !items[itOrbEmpathy]) return; for(int k: {-1, 1}) { @@ -5296,7 +5295,7 @@ void sideAttack(cell *mf, int dir, eMonster who, int bonus, eItem orb) { } } -void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) { +EX void sideAttack(cell *mf, int dir, eMonster who, int bonuskill) { int k = tkills(); sideAttack(mf, dir, who, 1, itOrbSide1); @@ -5327,7 +5326,7 @@ template void do_swords(cell *mf, cell *mt, eMonster who, const T& f) { } } -eMonster do_we_stab_a_friend(cell *mf, cell *mt, eMonster who) { +EX eMonster do_we_stab_a_friend(cell *mf, cell *mt, eMonster who) { eMonster m = moNone; do_swords(mf, mt, who, [&] (cell *c, int bb) { if(!peace::on && canAttack(mt, who, c, c->monst, AF_SWORD) && c->monst && isFriendly(c)) m = c->monst; @@ -5347,7 +5346,7 @@ eMonster do_we_stab_a_friend(cell *mf, cell *mt, eMonster who) { return m; } -void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill) { +EX void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill IS(0)) { int numsh = 0, numflail = 0, numlance = 0, numslash = 0, numbb[2]; numbb[0] = numbb[1] = 0; @@ -5434,17 +5433,17 @@ void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill) { } } -bool cellDangerous(cell *c) { +EX bool cellDangerous(cell *c) { return cellUnstableOrChasm(c) || isFire(c) || c->wall == waClosedGate; } // negative: die, attack friend, stay against rose, hit a wall, move against rose, hit the player -bool hasPrincessWeapon(eMonster m) { +EX bool hasPrincessWeapon(eMonster m) { return m == moPalace || m == moFatGuard; } -int stayvalue(eMonster m, cell *c) { +EX int stayvalue(eMonster m, cell *c) { if(!passable_for(c->monst, c, NULL, P_MONSTER | P_MIRROR)) return -1501; if(cellEdgeUnstable(c)) @@ -5454,7 +5453,7 @@ int stayvalue(eMonster m, cell *c) { } // friendly version of moveval -int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) { +EX int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) { int val = 0; if(isPlayerOn(c2)) val = -3000; @@ -5549,7 +5548,7 @@ int movevalue(eMonster m, cell *c, cell *c2, flagtype flags) { #define STRONGWIND 99 -void movegolems(flagtype flags) { +EX void movegolems(flagtype flags) { if(items[itOrbEmpathy] && items[itOrbSlaying]) flags |= AF_CRUSH; pathdata pd(moMouse); @@ -5641,16 +5640,16 @@ void movegolems(flagtype flags) { achievement_count("GOLEM", qg, 0); } -void sageheat(cell *c, double v) { +EX void sageheat(cell *c, double v) { HEAT(c) += v; if(c->wall == waFrozenLake && HEAT(c) > .6) c->wall = waLake; } -void activateFlashFrom(cell *cf, eMonster who, flagtype flags); +EX void activateFlashFrom(cell *cf, eMonster who, flagtype flags); bool sagefresh = true; -int nearestPathPlayer(cell *c) { +EX int nearestPathPlayer(cell *c) { for(int i=0; ipathdist < c->pathdist) return nearestPathPlayer(c2); for(int i=0; imonst == moGolemMoved) c->monst = moGolem; if(c->monst == moMouseMoved) c->monst = moMouse; if(c->monst == moPrincessMoved) c->monst = moPrincess; @@ -5837,17 +5836,17 @@ void refreshFriend(cell *c) { if(c->monst == moTameBomberbirdMoved) c->monst = moTameBomberbird; } -bool saved_tortoise_on(cell *c) { +EX bool saved_tortoise_on(cell *c) { return (c->monst == moTortoise && c->item == itBabyTortoise && !((tortoise::getb(c) ^ tortoise::babymap[c]) & tortoise::mask)); } -bool normal_gravity_at(cell *c) { +EX bool normal_gravity_at(cell *c) { return !in_gravity_zone(c); } -void moverefresh(bool turn = true) { +EX void moverefresh(bool turn IS(true)) { int dcs = isize(dcal); for(int i=0; imonst; if(movegroup(m) != moYeti) return; @@ -6092,7 +6091,7 @@ void consMove(cell *c, eMonster param) { movesofgood[0].push_back(c); } -void moveNormals(eMonster param) { +EX void moveNormals(eMonster param) { pathdata pd(param); for(int d=0; d<=MAX_EDGE; d++) movesofgood[d].clear(); @@ -6114,7 +6113,7 @@ void moveNormals(eMonster param) { } } -void markAmbush(cell *c, manual_celllister& cl) { +EX void markAmbush(cell *c, manual_celllister& cl) { if(!cl.add(c)) return; forCellEx(c2, c) if(c2->cpdist < c->cpdist) @@ -6124,7 +6123,7 @@ void markAmbush(cell *c, manual_celllister& cl) { int ambush_distance; bool ambushed; -void checkAmbushState() { +EX void checkAmbushState() { if(havewhat & HF_HUNTER) { manual_celllister cl; for(cell *c: dcal) { @@ -6161,7 +6160,7 @@ void checkAmbushState() { } -void movehex_all() { +EX void movehex_all() { for(int i: snaketypes) { movehex(false, i); if(!shmup::on && haveMount()) movehex(true, i); @@ -6170,7 +6169,7 @@ void movehex_all() { movehex_rest(true); } -void movemonsters() { +EX void movemonsters() { ambush_distance = 0; DEBB(DF_TURN, ("lava1")); @@ -6288,7 +6287,7 @@ void movemonsters() { // move the PC in direction d (or stay in place for d == -1) -bool checkNeedMove(bool checkonly, bool attacking) { +EX bool checkNeedMove(bool checkonly, bool attacking) { if(items[itOrbDomination] > ORBBASE && cwt.at->monst) return false; int flags = 0; @@ -6364,7 +6363,7 @@ bool checkNeedMove(bool checkonly, bool attacking) { return true; } -int countMyGolems(eMonster m) { +EX int countMyGolems(eMonster m) { int g=0, dcs = isize(dcal); for(int i=0; iitem == itOrbSafety || c->item == itOrbShield || @@ -6504,7 +6503,7 @@ bool hasSafeOrb(cell *c) { (c->item == itOrbYendor && yendor::state(c) == yendor::ysUnlocked); } -void checkmove() { +EX void checkmove() { if(dual::state == 2) return; @@ -6568,7 +6567,7 @@ void checkmove() { // move the PC. Warning: a very long function! todo: refactor -void placeGolem(cell *on, cell *moveto, eMonster m) { +EX void placeGolem(cell *on, cell *moveto, eMonster m) { if(on->monst == moFriendlyIvy) killMonster(on, moPlayer); if(on->monst) { @@ -6600,7 +6599,7 @@ void placeGolem(cell *on, cell *moveto, eMonster m) { } } -bool multiRevival(cell *on, cell *moveto) { +EX bool multiRevival(cell *on, cell *moveto) { int fl = 0; if(items[itOrbAether]) fl |= P_AETHER; if(items[itOrbFish]) fl |= P_FISH; @@ -6623,7 +6622,7 @@ bool multiRevival(cell *on, cell *moveto) { bool got_crossroads; -void movecost(cell* from, cell *to, int phase) { +EX void movecost(cell* from, cell *to, int phase) { if(from->land == laPower && to->land != laPower && (phase & 1)) { int n=0; for(int i=0; imaster->alt) return false; if(c2->item == itGrimoire && items[itGrimoire] > celldistAlt(c2)/-TEMPLE_EACH) { @@ -6680,12 +6679,12 @@ bool cantGetGrimoire(cell *c2, bool verbose = true) { return false; } -void gainLife() { +EX void gainLife() { items[itOrbLife] ++; if(items[itOrbLife] > 5 && !shmup::on) items[itOrbLife] = 5; } -void collectMessage(cell *c2, eItem which) { +EX void collectMessage(cell *c2, eItem which) { bool specialmode = yendor::on || princess::challenge || cheater || !in_full_game(); if(which == itDodeca && peace::on) return; @@ -6805,7 +6804,7 @@ void collectMessage(cell *c2, eItem which) { int ambushval; -int ambushSize(cell *c, eItem what) { +EX int ambushSize(cell *c, eItem what) { bool restricted = false; for(cell *c2: dcal) { if(c2->cpdist > 3) break; @@ -6888,7 +6887,7 @@ int ambushSize(cell *c, eItem what) { } -int ambush(cell *c, eItem what) { +EX int ambush(cell *c, eItem what) { int maxdist = gamerange(); celllister cl(c, maxdist, 1000000, NULL); cell *c0 = c; @@ -6956,11 +6955,11 @@ int ambush(cell *c, eItem what) { return dogs + dogs0; } -bool cannotPickupItem(cell *c, bool telekinesis) { +EX bool cannotPickupItem(cell *c, bool telekinesis) { return itemHidden(c) && !telekinesis && !(isWatery(c) && markOrb(itOrbFish)); } -bool canPickupItemWithMagnetism(cell *c, cell *from) { +EX bool canPickupItemWithMagnetism(cell *c, cell *from) { if(!c->item || c->item == itOrbYendor || isWall(c) || cannotPickupItem(c, false)) return false; if(c->item == itCompass && from->item) @@ -6968,7 +6967,7 @@ bool canPickupItemWithMagnetism(cell *c, cell *from) { return true; } -bool doPickupItemsWithMagnetism(cell *c) { +EX bool doPickupItemsWithMagnetism(cell *c) { cell *csaf = NULL; if(items[itOrbMagnetism]) forCellEx(c3, c) if(canPickupItemWithMagnetism(c3, c)) { @@ -6986,7 +6985,7 @@ bool doPickupItemsWithMagnetism(cell *c) { return false; } -void pickupMovedItems(cell *c) { +EX void pickupMovedItems(cell *c) { if(!c->item) return; if(c->item == itOrbSafety) return; if(isPlayerOn(c)) collectItem(c, true); @@ -6996,7 +6995,7 @@ void pickupMovedItems(cell *c) { collectItem(c, true); } -bool collectItem(cell *c2, bool telekinesis) { +EX bool collectItem(cell *c2, bool telekinesis IS(false)) { int pg = gold(); bool dopickup = true; @@ -7244,7 +7243,7 @@ bool collectItem(cell *c2, bool telekinesis) { return false; } -void glance_message() { +EX void glance_message() { if(gold() >= 300) addMessage(XLAT("You feel great, like a true treasure hunter.")); else if(gold() >= 200) @@ -7261,7 +7260,7 @@ void glance_message() { addMessage(XLAT("Your inventory is empty.")); } -void dropGreenStone(cell *c) { +EX void dropGreenStone(cell *c) { if(items[itGreenStone] && !passable(c, NULL, P_MONSTER)) { // NOTE: PL/CZ translations assume that itGreenStone is dropped to avoid extra forms! addMessage(XLAT("Cannot drop %the1 here!", itGreenStone)); @@ -7293,7 +7292,7 @@ void dropGreenStone(cell *c) { } } -void roundTableMessage(cell *c2) { +EX void roundTableMessage(cell *c2) { if(!euclid && !cwt.at->master->alt) return; if(!euclid && !c2->master->alt) return; int dd = celldistAltRelative(c2) - celldistAltRelative(cwt.at); @@ -7320,7 +7319,7 @@ void roundTableMessage(cell *c2) { } } -bool in_full_game() { +EX bool in_full_game() { if(tactic::on) return false; if(princess::challenge) return false; if(chaosmode) return true; @@ -7331,7 +7330,7 @@ bool in_full_game() { return false; } -void knightFlavorMessage(cell *c2) { +EX void knightFlavorMessage(cell *c2) { if(!eubinary && !c2->master->alt) { addMessage(XLAT("\"I am lost...\"")); @@ -7449,13 +7448,13 @@ int mine_adjacency_rule = 0; map> adj_memo; -bool geometry_has_alt_mine_rule() { +EX bool geometry_has_alt_mine_rule() { if(WDIM == 2) return VALENCE > 3; if(WDIM == 3) return !among(geometry, gHoroHex, gCell5, gBitrunc3, gCell8, gECell8, gCell120, gECell120); return true; } -vector adj_minefield_cells(cell *c) { +EX vector adj_minefield_cells(cell *c) { vector res; if(mine_adjacency_rule == 0 || !geometry_has_alt_mine_rule()) forCellCM(c2, c) res.push_back(c2); @@ -7494,12 +7493,12 @@ vector adj_minefield_cells(cell *c) { return res; } -void auto_teleport_charges() { +EX void auto_teleport_charges() { if(specialland == laMinefield && firstland == laMinefield && bounded) items[itOrbTeleport] = isFire(cwt.at->wall) ? 0 : 1; } -bool uncoverMines(cell *c, int lev, int dist, bool just_checking) { +EX bool uncoverMines(cell *c, int lev, int dist, bool just_checking) { bool b = false; if(c->wall == waMineMine && just_checking) return true; if(c->wall == waMineUnknown) { @@ -7591,7 +7590,7 @@ namespace orbbull { // predictable or not static constexpr bool randterra = false; -void terracotta(cell *c) { +EX void terracotta(cell *c) { if(c->wall == waTerraWarrior && !c->monst && !racing::on) { bool live = false; if(randterra) { @@ -7612,12 +7611,12 @@ void terracotta(cell *c) { } } -void terracottaAround(cell *c) { +EX void terracottaAround(cell *c) { forCellEx(c2, c) terracotta(c2); } -void terracotta() { +EX void terracotta() { for(int i=0; iwall; if(th->land == laAlchemist) th->wall = isAlch(cwt.at) ? cwt.at->wall : cto->wall; @@ -7750,7 +7749,7 @@ void pushThumper(cell *th, cell *cto) { cto->wparam = th->wparam; } -bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) { +EX bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) { if(tgt->wall == waBoat || tgt->wall == waStrandedBoat) return false; if(isReptile(tgt->wall)) return false; if(isWatery(tgt) && !tgt->monst) @@ -7763,7 +7762,7 @@ bool canPushThumperOn(cell *tgt, cell *thumper, cell *player) { !tgt->item; } -void activateActiv(cell *c, bool msg) { +EX void activateActiv(cell *c, bool msg) { if(msg) addMessage(XLAT("You activate %the1.", c->wall)); if(c->wall == waThumperOff) { playSound(c, "click"); @@ -7776,11 +7775,11 @@ void activateActiv(cell *c, bool msg) { c->wparam = 100; } -bool scentResistant() { +EX bool scentResistant() { return markOrb(itOrbBeauty) || markOrb(itOrbAether) || markOrb(itOrbShield); } -void wouldkill(const char *msg) { +EX void wouldkill(const char *msg) { if(who_kills_me == moWarning) addMessage(XLAT("This move appears dangerous -- are you sure?")); else if(who_kills_me == moFireball) @@ -7791,7 +7790,7 @@ void wouldkill(const char *msg) { addMessage(XLAT(msg, who_kills_me)); } -bool havePushConflict(cell *pushto, bool checkonly) { +EX bool havePushConflict(cell *pushto, bool checkonly) { if(pushto && multi::activePlayers() > 1) { for(int i=0; imonst == moFriendlyIvy) killMonster(c2, moPlayer, 0); } -bool monsterPushable(cell *c2) { +EX bool monsterPushable(cell *c2) { return (c2->monst != moFatGuard && !(isMetalBeast(c2->monst) && c2->stuntime < 2) && c2->monst != moTortoise && c2->monst != moTerraWarrior && c2->monst != moVizier); } bool got_survivalist; -bool should_switchplace(cell *c1, cell *c2) { +EX bool should_switchplace(cell *c1, cell *c2) { if(isPrincess(c2->monst) || among(c2->monst, moGolem, moIllusion, moMouse, moFriendlyGhost)) return true; @@ -7831,13 +7830,13 @@ bool should_switchplace(cell *c1, cell *c2) { return false; } -bool warningprotection_hit(eMonster m) { +EX bool warningprotection_hit(eMonster m) { if(m && warningprotection(XLAT("Are you sure you want to hit %the1?", m))) return true; return false; } -bool switchplace_prevent(cell *c1, cell *c2, bool checkonly) { +EX bool switchplace_prevent(cell *c1, cell *c2, bool checkonly) { if(!should_switchplace(c1, c2)) return false; if(c1->monst && c1->monst != moFriendlyIvy) { if(!checkonly) addMessage(XLAT("There is no room for %the1!", c2->monst)); @@ -7848,7 +7847,7 @@ bool switchplace_prevent(cell *c1, cell *c2, bool checkonly) { return false; } -void handle_switchplaces(cell *c1, cell *c2, bool& switchplaces) { +EX void handle_switchplaces(cell *c1, cell *c2, bool& switchplaces) { if(should_switchplace(c1, c2)) { bool pswitch = false; if(c2->monst == moMouse) @@ -7869,7 +7868,7 @@ void handle_switchplaces(cell *c1, cell *c2, bool& switchplaces) { } } -bool movepcto(int d, int subdir, bool checkonly) { +EX bool movepcto(int d, int subdir IS(1), bool checkonly IS(false)) { if(dual::state == 1) return dual::movepc(d, subdir, checkonly); if(d >= 0 && !checkonly && subdir != 1 && subdir != -1) printf("subdir = %d\n", subdir); global_pushto = NULL; @@ -8515,7 +8514,7 @@ bool movepcto(int d, int subdir, bool checkonly) { !(isWorm(dst) || dst->monst == moShadow); } */ -void moveItem1(cell *from, cell *to, bool activateYendor) { +EX void moveItem1(cell *from, cell *to, bool activateYendor) { if(from->item == itOrbYendor) { bool xnew = true; for(int i=0; iitem = i; } -void moveItem (cell *from, cell *to, bool activateYendor) { +EX void moveItem (cell *from, cell *to, bool activateYendor) { static cell dummy; dummy.item = itNone; moveItem1(from, &dummy, activateYendor); @@ -8551,7 +8550,7 @@ void moveItem (cell *from, cell *to, bool activateYendor) { moveItem1(&dummy, to, activateYendor); } -void fixWormBug(cell *c) { +EX void fixWormBug(cell *c) { if(conformal::includeHistory) return; printf("worm bug!\n"); if(c->monst == moWormtail) c->monst = moWormwait; @@ -8559,7 +8558,7 @@ void fixWormBug(cell *c) { if(c->monst == moHexSnakeTail) c->monst = moHexSnake; } -cell *wormhead(cell *c) { +EX cell *wormhead(cell *c) { // cell *cor = c; findhead: if(c->monst == moTentacle || c->monst == moWorm || c->monst == moHexSnake || @@ -8573,7 +8572,7 @@ cell *wormhead(cell *c) { return c; } -int wormpos(cell *c) { +EX int wormpos(cell *c) { // cell *cor = c; int cnt = 0; findhead: @@ -8589,7 +8588,7 @@ int wormpos(cell *c) { } // currently works for worms only -bool sameMonster(cell *c1, cell *c2) { +EX bool sameMonster(cell *c1, cell *c2) { if(!c1 || !c2) return false; if(c1 == c2) return true; if(isWorm(c1->monst) && isWorm(c2->monst)) @@ -8599,7 +8598,7 @@ bool sameMonster(cell *c1, cell *c2) { return false; } -eMonster haveMount() { +EX eMonster haveMount() { for(int i=0; imonst; if(m) return m; @@ -8607,13 +8606,13 @@ eMonster haveMount() { return moNone; } -bool mightBeMine(cell *c) { +EX bool mightBeMine(cell *c) { return c->wall == waMineUnknown || c->wall == waMineMine; } hookset *hooks_mark; -void performMarkCommand(cell *c) { +EX void performMarkCommand(cell *c) { if(!c) return; if(callhandlers(false, hooks_mark, c)) return; if(c->land == laCA && c->wall == waNone) @@ -8628,25 +8627,25 @@ void performMarkCommand(cell *c) { if(adj) c->landparam ^= 1; } -bool mineMarked(cell *c) { +EX bool mineMarked(cell *c) { if(!mightBeMine(c)) return false; if(c->item) return false; if(c->land != laMinefield) return true; return c->landparam & 1; } -bool mineMarkedSafe(cell *c) { +EX bool mineMarkedSafe(cell *c) { if(!mightBeMine(c)) return false; if(c->item) return true; if(c->land != laMinefield) return false; return c->landparam & 2; } -bool minesafe() { +EX bool minesafe() { return items[itOrbAether]; } -bool warningprotection(const string& s) { +EX bool warningprotection(const string& s) { if(hardcore) return false; if(multi::activePlayers() > 1) return false; if(items[itWarning]) return false; diff --git a/geometry.cpp b/geometry.cpp index 63c9a01d..6cf4faf5 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -356,9 +356,9 @@ namespace geom3 { } } -namespace geom3 { +EX namespace geom3 { #if MAXMDIM >= 4 -void switch_always3() { +EX void switch_always3() { if(dual::split(switch_always3)) return; if(rug::rugged) rug::close(); vid.always3 = !vid.always3; @@ -367,7 +367,7 @@ void switch_always3() { } #endif - void switch_tpp() { + EX void switch_tpp() { if(dual::split(switch_fpp)) return; if(pmodel == mdDisk && vid.camera_angle) { vid.yshift = 0; @@ -388,7 +388,7 @@ void switch_always3() { } } - void switch_fpp() { + EX void switch_fpp() { #if MAXMDIM >= 4 if(rug::rugged) rug::close(); if(dual::split(switch_fpp)) return; @@ -429,7 +429,7 @@ void switch_always3() { #endif } - } + EX } geometry_information *cgip; map cgis; diff --git a/geometry2.cpp b/geometry2.cpp index 9aec1546..578d934a 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -19,7 +19,7 @@ void fixelliptic(hyperpoint& h) { for(int i=0; irelative_matrix(c2, c1, point_hint); } @@ -161,7 +161,7 @@ transmatrix hrmap_standard::relative_matrix(cell *c2, cell *c1, const hyperpoint return gm * where; } -transmatrix &ggmatrix(cell *c) { +EX transmatrix &ggmatrix(cell *c) { transmatrix& t = gmatrix[c]; if(t[GDIM][GDIM] == 0) { if(euwrap && centerover.at && masterless) @@ -176,7 +176,7 @@ transmatrix &ggmatrix(cell *c) { return t; } -transmatrix calc_relative_matrix_help(cell *c, heptagon *h1) { +EX transmatrix calc_relative_matrix_help(cell *c, heptagon *h1) { transmatrix gm = Id; heptagon *h2 = c->master; transmatrix where = Id; @@ -342,11 +342,11 @@ void virtualRebase(cell*& base, T& at, bool tohex, const U& check) { } -void virtualRebase(cell*& base, transmatrix& at, bool tohex) { +EX void virtualRebase(cell*& base, transmatrix& at, bool tohex) { virtualRebase(base, at, tohex, tC0); } -void virtualRebase(cell*& base, hyperpoint& h, bool tohex) { +EX void virtualRebase(cell*& base, hyperpoint& h, bool tohex) { // we perform fixing in check, so that it works with larger range virtualRebase(base, h, tohex, [] (const hyperpoint& h) { if(hyperbolic && GDIM == 2) return hpxy(h[0], h[1]); @@ -356,7 +356,7 @@ void virtualRebase(cell*& base, hyperpoint& h, bool tohex) { } // works only in geometries similar to the standard one, and only on heptagons -void virtualRebaseSimple(heptagon*& base, transmatrix& at) { +EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) { while(true) { @@ -390,7 +390,7 @@ void virtualRebaseSimple(heptagon*& base, transmatrix& at) { } } -double cellgfxdist(cell *c, int i) { +EX double cellgfxdist(cell *c, int i) { if(euclid && !penrose && !archimedean) { if(c->type == 8 && (i&1)) return cgi.crossf * sqrt(2); return cgi.crossf; @@ -399,7 +399,7 @@ double cellgfxdist(cell *c, int i) { return !BITRUNCATED ? cgi.tessf : (c->type == 6 && (i&1)) ? cgi.hexhexdist : cgi.crossf; } -transmatrix cellrelmatrix(cell *c, int i) { +EX transmatrix cellrelmatrix(cell *c, int i) { if(NONSTDVAR || archimedean || penrose) return calc_relative_matrix(c->move(i), c, i); double d = cellgfxdist(c, i); transmatrix T = ddspin(c, i) * xpush(d); @@ -408,9 +408,9 @@ transmatrix cellrelmatrix(cell *c, int i) { return T; } -double randd() { return (rand() + .5) / (RAND_MAX + 1.); } +EX double randd() { return (rand() + .5) / (RAND_MAX + 1.); } -hyperpoint randomPointIn(int t) { +EX hyperpoint randomPointIn(int t) { if(NONSTDVAR || archimedean || penrose) { // Let these geometries be less confusing. // Also easier to implement ;) @@ -425,7 +425,7 @@ hyperpoint randomPointIn(int t) { } } -hyperpoint get_corner_position(cell *c, int cid, ld cf) { +EX hyperpoint get_corner_position(cell *c, int cid, ld cf IS(3)) { #if CAP_GP if(GOLDBERG) return gp::get_corner_position(c, cid, cf); #endif @@ -478,9 +478,9 @@ hyperpoint get_corner_position(cell *c, int cid, ld cf) { return C0; } -bool approx_nearcorner = false; +EX bool approx_nearcorner = false; -hyperpoint nearcorner(cell *c, int i) { +EX hyperpoint nearcorner(cell *c, int i) { if(GOLDBERG) { cellwalker cw(c, i); cw += wstep; @@ -560,7 +560,7 @@ hyperpoint nearcorner(cell *c, int i) { return ddspin(c, i) * xpush0(d); } -hyperpoint farcorner(cell *c, int i, int which) { +EX hyperpoint farcorner(cell *c, int i, int which) { #if CAP_GP if(GOLDBERG) { cellwalker cw(c, i); @@ -623,13 +623,13 @@ hyperpoint farcorner(cell *c, int i, int which) { return cellrelmatrix(c, i) * get_corner_position(c->move(i), (cellwalker(c, i) + wstep + (which?-1:2)).spin); } -hyperpoint midcorner(cell *c, int i, ld v) { +EX hyperpoint midcorner(cell *c, int i, ld v) { auto hcor = farcorner(c, i, 0); auto tcor = get_corner_position(c, i, 3); return mid_at(tcor, hcor, v); } -hyperpoint get_warp_corner(cell *c, int cid) { +EX hyperpoint get_warp_corner(cell *c, int cid) { // midcorner(c, cid, .5) but sometimes easier versions exist #if CAP_GP if(GOLDBERG) return gp::get_corner_position(c, cid, 2); diff --git a/graph.cpp b/graph.cpp index 8f03471e..38625f68 100644 --- a/graph.cpp +++ b/graph.cpp @@ -8,21 +8,21 @@ namespace hr { int last_firelimit, firelimit; -int inmirrorcount = 0; +EX int inmirrorcount = 0; bool spatial_graphics; bool wmspatial, wmescher, wmplain, wmblack, wmascii; bool mmspatial, mmhigh, mmmon, mmitem; -int detaillevel = 0; +EX int detaillevel = 0; -bool first_cell_to_draw = true; +EX bool first_cell_to_draw = true; -bool in_perspective() { +EX bool in_perspective() { return among(pmodel, mdPerspective, mdGeodesic); } -bool hide_player() { +EX bool hide_player() { return DIM == 3 && playermoved && vid.yshift == 0 && vid.sspeed > -5 && in_perspective() && (first_cell_to_draw || elliptic) && (WDIM == 3 || vid.camera == 0) && !inmirrorcount #if CAP_RACING && !(racing::on && !racing::standard_centering && !racing::player_relative && !sol) @@ -30,30 +30,30 @@ bool hide_player() { ; } -hookset *hooks_handleKey; -hookset *hooks_drawcell; -purehookset hooks_frame, hooks_markers; +EX hookset *hooks_handleKey; +EX hookset *hooks_drawcell; +EX purehookset hooks_frame, hooks_markers; -ld animation_factor = 1; -int animation_lcm = 0; +EX ld animation_factor = 1; +EX int animation_lcm = 0; -ld ptick(int period, ld phase) { +EX ld ptick(int period, ld phase IS(0)) { if(animation_lcm) animation_lcm = animation_lcm * (period / gcd(animation_lcm, period)); return (ticks * animation_factor) / period + phase * 2 * M_PI; } -ld fractick(int period, ld phase = 0) { +EX ld fractick(int period, ld phase IS(0)) { ld t = ptick(period, phase) / 2 / M_PI; t -= floor(t); if(t<0) t++; return t; } -ld sintick(int period, ld phase) { +EX ld sintick(int period, ld phase IS(0)) { return sin(ptick(period, phase)); } -transmatrix spintick(int period, ld phase = 0) { +EX transmatrix spintick(int period, ld phase IS(0)) { return spin(ptick(period, phase)); } @@ -65,26 +65,26 @@ transmatrix spintick(int period, ld phase = 0) { int colorbar; -bool inHighQual; // taking high quality screenshot +EX bool inHighQual; // taking high quality screenshot bool auraNOGL; // aura without GL // int axestate; -int ticks; +EX int ticks; int frameid; bool camelotcheat; -bool nomap; +EX bool nomap; eItem orbToTarget; eMonster monsterToSummon; int sightrange_bonus = 0; -string mouseovers; +EX string mouseovers; -int darken = 0; +EX int darken = 0; struct fallanim { int t_mon, t_floor, pid; @@ -95,7 +95,7 @@ struct fallanim { map fallanims; -bool doHighlight() { +EX bool doHighlight() { return (hiliteclick && darken < 2) ? !mmhigh : mmhigh; } @@ -106,7 +106,7 @@ ld spina(cell *c, int dir) { } // cloak color -int cloakcolor(int rtr) { +EX int cloakcolor(int rtr) { rtr -= 28; rtr /= 2; rtr %= 10; @@ -123,19 +123,19 @@ int firegradient(double p) { return gradient(0xFFFF00, 0xFF0000, 0, p, 1); } -int firecolor(int phase, int mul) { +EX int firecolor(int phase IS(0), int mul IS(1)) { return gradient(0xFFFF00, 0xFF0000, -1, sintick(100*mul, phase/200./M_PI), 1); } -int watercolor(int phase) { +EX int watercolor(int phase) { return 0x0080C0FF + 256 * int(63 * sintick(50, phase/100./M_PI)); } -int aircolor(int phase) { +EX int aircolor(int phase) { return 0x8080FF00 | int(32 + 32 * sintick(200, phase * 1. / cgi.S21)); } -int fghostcolor(cell *c) { +EX int fghostcolor(cell *c) { int phase = int(fractick(650, (int)(size_t)c) * 4000); if(phase < 1000) return gradient(0xFFFF80, 0xA0C0FF, 0, phase, 1000); else if(phase < 2000) return gradient(0xA0C0FF, 0xFF80FF, 1000, phase, 2000); @@ -144,7 +144,7 @@ int fghostcolor(cell *c) { return 0xFFD500; } -int weakfirecolor(int phase) { +EX int weakfirecolor(int phase) { return gradient(0xFF8000, 0xFF0000, -1, sintick(500, phase/1000./M_PI), 1); } @@ -162,8 +162,8 @@ color_t fc(int ph, color_t col, int z) { } int lightat, safetyat; -void drawLightning() { lightat = ticks; } -void drawSafety() { safetyat = ticks; } +EX void drawLightning() { lightat = ticks; } +EX void drawSafety() { safetyat = ticks; } void drawShield(const transmatrix& V, eItem it) { #if CAP_CURVE @@ -315,7 +315,7 @@ void drawLightning(const transmatrix& V) { #endif } -ld displayspin(cell *c, int d) { +EX ld displayspin(cell *c, int d) { if(0); #if CAP_ARCM else if(archimedean) { @@ -363,13 +363,13 @@ double hexshiftat(cell *c) { return 0; } -transmatrix ddspin(cell *c, int d, ld bonus) { +EX transmatrix ddspin(cell *c, int d, ld bonus IS(0)) { if(WDIM == 3 && d < c->type) return rspintox(tC0(calc_relative_matrix(c->cmove(d), c, C0))) * cspin(2, 0, bonus); if(WDIM == 2 && (binarytiling || penrose) && d < c->type) return spin(bonus) * rspintox(nearcorner(c, d)); return spin(displayspin(c, d) + bonus - hexshiftat(c)); } -transmatrix iddspin(cell *c, int d, ld bonus) { +EX transmatrix iddspin(cell *c, int d, ld bonus IS(0)) { if(WDIM == 3 && d < c->type) return cspin(0, 2, bonus) * spintox(tC0(calc_relative_matrix(c->cmove(d), c, C0))); if(WDIM == 2 && (binarytiling || penrose) && d < c->type) return spin(bonus) * spintox(nearcorner(c, d)); return spin(hexshiftat(c) - displayspin(c, d) + bonus); @@ -617,7 +617,7 @@ void animallegs(const transmatrix& V, eMonster mo, color_t col, double footphase #endif } -bool noshadow; +EX bool noshadow; #if CAP_SHAPES void ShadowV(const transmatrix& V, const hpcshape& bp, PPR prio) { @@ -1256,7 +1256,7 @@ void drawPlayer(eMonster m, cell *where, const transmatrix& V, color_t col, doub } } -int wingphase(int period, int phase) { +EX int wingphase(int period, int phase IS(0)) { ld t = fractick(period, phase); const int WINGS2 = WINGS * 2; int ti = int(t * WINGS2) % WINGS2; @@ -2410,7 +2410,7 @@ void drawWormSegments() { last_wormsegment = -1; } -bool dont_face_pc = false; +EX bool dont_face_pc = false; bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool mirrored, color_t asciicol) { #if CAP_SHAPES @@ -2831,7 +2831,7 @@ ld straightDownSpeed; array,AURA+1> aurac; -bool haveaura() { +EX bool haveaura() { if(!(vid.aurastr>0 && !svg::in && (auraNOGL || vid.usingGL))) return false; if(sphere && mdAzimuthalEqui()) return true; if(among(pmodel, mdJoukowsky, mdJoukowskyInverted) && hyperbolic && conformal::model_transition < 1) @@ -2843,7 +2843,7 @@ vector > auraspecials; int auramemo; -void clearaura() { +EX void clearaura() { if(!haveaura()) return; for(int a=0; a 0; #endif @@ -3878,11 +3878,11 @@ bool has_nice_dual() { } // does the current geometry allow nice duals -bool is_nice_dual(cell *c) { +EX bool is_nice_dual(cell *c) { return c->land == laDual && has_nice_dual(); } -bool use_swapped_duals() { +EX bool use_swapped_duals() { return (masterless && !a4) || GOLDBERG; } @@ -4104,7 +4104,7 @@ bool allemptynear(cell *c) { static const int trapcol[4] = {0x904040, 0xA02020, 0xD00000, 0x303030}; static const int terracol[8] = {0xD000, 0xE25050, 0xD0D0D0, 0x606060, 0x303030, 0x181818, 0x0080, 0x8080}; -bool bright; +EX bool bright; // how much to darken int getfd(cell *c) { @@ -4493,7 +4493,7 @@ ld mousedist(transmatrix T) { } vector clipping_planes; -int noclipped; +EX int noclipped; void make_clipping_planes() { #if MAXMDIM >= 4 @@ -4516,7 +4516,7 @@ void make_clipping_planes() { #endif } -void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& V2, const hyperpoint h2, color_t col, int prec) { +EX void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& V2, const hyperpoint h2, color_t col, int prec) { #if MAXMDIM >= 4 if(WDIM == 2 && GDIM == 3) { ld eps = cgi.human_height/100; @@ -4528,7 +4528,7 @@ void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& V2, queueline(V1*h1, V2*h2, col, prec); } -void gridline(const transmatrix& V, const hyperpoint h1, const hyperpoint h2, color_t col, int prec) { +EX void gridline(const transmatrix& V, const hyperpoint h1, const hyperpoint h2, color_t col, int prec) { gridline(V, h1, V, h2, col, prec); } @@ -6731,25 +6731,25 @@ struct flashdata { vector flashes; -void drawFlash(cell *c) { +EX void drawFlash(cell *c) { flashes.push_back(flashdata(ticks, 1000, c, iinf[itOrbFlash].color, 0)); } -void drawBigFlash(cell *c) { +EX void drawBigFlash(cell *c) { flashes.push_back(flashdata(ticks, 2000, c, 0xC0FF00, 0)); } -void drawParticleSpeed(cell *c, color_t col, int speed) { +EX void drawParticleSpeed(cell *c, color_t col, int speed) { if(vid.particles && !confusingGeometry()) flashes.push_back(flashdata(ticks, rand() % 16, c, col, speed)); } -void drawParticle(cell *c, color_t col, int maxspeed) { +EX void drawParticle(cell *c, color_t col, int maxspeed IS(100)) { drawParticleSpeed(c, col, 1 + rand() % maxspeed); } -void drawParticles(cell *c, color_t col, int qty, int maxspeed) { +EX void drawParticles(cell *c, color_t col, int qty, int maxspeed IS(100)) { if(vid.particles) while(qty--) drawParticle(c,col, maxspeed); } -void drawFireParticles(cell *c, int qty, int maxspeed) { +EX void drawFireParticles(cell *c, int qty, int maxspeed IS(100)) { if(vid.particles) for(int i=0; i wrap_drawfullmap = drawfullmap; bool force_sphere_outline = false; -void drawfullmap() { +EX void drawfullmap() { DEBBI(DF_GRAPH, ("draw full map")); @@ -7577,7 +7577,7 @@ void drawfullmap() { extern bool wclick; #endif -void gamescreen(int _darken) { +EX void gamescreen(int _darken) { if(subscreens::split([=] () { calcparam(); @@ -7653,9 +7653,9 @@ void gamescreen(int _darken) { #endif } -bool nohelp; +EX bool nohelp; -void normalscreen() { +EX void normalscreen() { help = "@"; mouseovers = XLAT("Press F1 or right click for help"); @@ -7688,7 +7688,7 @@ vector< function > screens = { normalscreen }; int cmode; -void drawscreen() { +EX void drawscreen() { DEBBI(DF_GRAPH, ("drawscreen")); @@ -7713,6 +7713,8 @@ void drawscreen() { SDL_FillRect(s, NULL, backcolor); #endif + // displaynum(vx,100, 0, 24, 0xc0c0c0, celldist(cwt.at), ":"); + lgetcstat = getcstat; getcstat = 0; inslider = false; @@ -7792,7 +7794,7 @@ void drawscreen() { //printf("\ec"); } -void restartGraph() { +EX void restartGraph() { DEBBI(DF_INIT, ("restartGraph")); View = Id; @@ -7810,7 +7812,7 @@ void restartGraph() { } } -void clearAnimations() { +EX void clearAnimations() { for(int i=0; i= 5) return; // no animations! transmatrix T; if(!compute_relamatrix(src, tgt, direction_hint, T)) return; @@ -7878,7 +7880,7 @@ void animateMovement(cell *src, cell *tgt, int layer, int direction_hint) { } } -void animateAttack(cell *src, cell *tgt, int layer, int direction_hint) { +EX void animateAttack(cell *src, cell *tgt, int layer, int direction_hint) { if(vid.mspeed >= 5) return; // no animations! transmatrix T; if(!compute_relamatrix(src, tgt, direction_hint, T)) return; @@ -7891,7 +7893,7 @@ void animateAttack(cell *src, cell *tgt, int layer, int direction_hint) { vector > animstack; -void indAnimateMovement(cell *src, cell *tgt, int layer, int direction_hint) { +EX void indAnimateMovement(cell *src, cell *tgt, int layer, int direction_hint) { if(vid.mspeed >= 5) return; // no animations! if(animations[layer].count(tgt)) { animation res = animations[layer][tgt]; @@ -7910,13 +7912,13 @@ void indAnimateMovement(cell *src, cell *tgt, int layer, int direction_hint) { } } -void commitAnimations(int layer) { +EX void commitAnimations(int layer) { for(int i=0; i= 5) return; // no animations! static cell c1; gmatrix[&c1] = gmatrix[b]; c1.master = b->master; @@ -7935,12 +7937,12 @@ void drawBug(const cellwalker& cw, color_t col) { #endif } -cell *viewcenter() { +EX cell *viewcenter() { if(masterless) return centerover.at; else return viewctr.at->c7; } -bool inscreenrange(cell *c) { +EX bool inscreenrange(cell *c) { if(sphere) return true; if(euclid) return celldistance(viewcenter(), c) <= get_sightrange_ambush(); if(nonisotropic) return gmatrix.count(c); diff --git a/help.cpp b/help.cpp index 8d0eb5c6..4cbc5d59 100644 --- a/help.cpp +++ b/help.cpp @@ -3,11 +3,11 @@ namespace hr { -string help; +EX string help; -function help_delegate; +EX function help_delegate; -vector help_extensions; +EX vector help_extensions; vector extra_keys = { "1 = orthogonal/Gans model", @@ -726,9 +726,9 @@ void appendHelp(string s) { unsigned char lastval; int windtotal; -hookset *hooks_mouseover; +EX hookset *hooks_mouseover; -void describeMouseover() { +EX void describeMouseover() { DEBBI(DF_GRAPH, ("describeMouseover")); cell *c = mousing ? mouseover : playermoved ? NULL : centerover.at; @@ -884,7 +884,7 @@ void describeMouseover() { if(mousey < vid.fsize * 3/2) getcstat = SDLK_F1; } -void showHelp() { +EX void showHelp() { cmode = sm::HELP | sm::DOTOUR; getcstat = SDLK_ESCAPE; if(help == "HELPFUN") { @@ -937,10 +937,9 @@ void showHelp() { }; } - hookset *hooks_default_help; -void gotoHelp(const string& h) { +EX void gotoHelp(const string& h) { help = h; help_extensions.clear(); pushScreen(showHelp); @@ -962,7 +961,7 @@ void gotoHelp(const string& h) { if(help == "HELPGEN") helpgenerator(); } -void subhelp(const string& h) { +EX void subhelp(const string& h) { string oldhelp = help; auto ext = help_extensions; reaction_t back = [oldhelp, ext] () { @@ -975,7 +974,7 @@ void subhelp(const string& h) { help_extensions.push_back(help_extension{'z', XLAT("back"), back}); } -void gotoHelpFor(eLand l) { +EX void gotoHelpFor(eLand l) { help = generateHelpForLand(l); int beastcount = 0; diff --git a/hud.cpp b/hud.cpp index 16d0ebe1..2f4d6e00 100644 --- a/hud.cpp +++ b/hud.cpp @@ -3,18 +3,18 @@ namespace hr { -vector radarpoints; -vector radarlines; +EX vector radarpoints; +EX vector radarlines; -purehookset hooks_stats; +EX purehookset hooks_stats; -int monsterclass(eMonster m) { +EX int monsterclass(eMonster m) { if(isFriendly(m) || m == moTortoise) return 1; else if(isMonsterPart(m)) return 2; else return 0; } -int glyphclass(int i) { +EX int glyphclass(int i) { if(i < ittypes) { eItem it = eItem(i); return itemclass(it) == IC_TREASURE ? 0 : 1; @@ -25,7 +25,7 @@ int glyphclass(int i) { } } -int subclass(int i) { +EX int subclass(int i) { if(i < ittypes) return itemclass(eItem(i)); else @@ -304,9 +304,9 @@ void displayglyph2(int cx, int cy, int buttonsize, int i) { } } -bool nohud, nomenukey; +EX bool nohud, nomenukey; -hookset *hooks_prestats; +EX hookset *hooks_prestats; #if CAP_SHAPES void drawMobileArrow(int i) { @@ -350,9 +350,9 @@ void drawMobileArrow(int i) { } #endif -bool nofps = false; +EX bool nofps = false; -void draw_radar(bool cornermode) { +EX void draw_radar(bool cornermode) { if(dual::split([] { dual::in_subscreen([] { calcparam(); draw_radar(false); }); })) return; bool d3 = WDIM == 3; @@ -442,7 +442,7 @@ void draw_radar(bool cornermode) { } } -void drawStats() { +EX void drawStats() { if(nohud || vid.stereo_mode == sLR) return; if(callhandlers(false, hooks_prestats)) return; if(viewdists && show_distance_lists) diff --git a/hyper.h b/hyper.h index 87cf5dda..0c6f5062 100644 --- a/hyper.h +++ b/hyper.h @@ -337,8 +337,6 @@ extern videopar vid; #define DIM GDIM #define MDIM (DIM+1) -extern array sightranges; - #define self (*this) struct hyperpoint : array { @@ -458,7 +456,8 @@ inline hyperpoint point31(ld x, ld y, ld z) { return hyperpoint(x,y,z,1); } inline hyperpoint point2(ld x, ld y) { return hyperpoint(x,y,0,0); } extern int cellcount, heptacount; - +extern color_t forecolor; +extern ld band_shift; // cell information for the game struct gcell { @@ -820,68 +819,15 @@ string XLATN(string x); // translate the sentence x string cts(char c); // character to string string its(int i); // int to string string itsh8(int i); // int to string (8 hex digits) - -// a random integer from [0..i), generated by the game's main generator -// we want the same world to be generated if the seed is the same. For this purpose, -// hrand should be used for all the game-related generation, and nowhere else -int hrand(int i); +string itsh(int i); // int to string // size casted to int, to prevent warnings and actual errors caused by the unsignedness of x.size() template int isize(const T& x) {return x.size(); } -// initialize the achievement system. -void achievement_init(); - -// close the achievement system. -void achievement_close(); - -// get the user name -string myname(); - -// gain the achievement with the given name. -// flags: 'e' - for Euclidean, 's' - for Shmup, '7' - for heptagonal -// Only awarded if special modes are matched exactly. -void achievement_gain(const char*, char flags = 0); - -// gain the achievement for collecting a number of 'it'. -void achievement_collection(eItem it, int prevgold, int newgold); - -// this is used for 'counting' achievements, such as kill 10 -// monsters at the same time. -void achievement_count(const string& s, int current, int prev); - -// scores for special challenges -void achievement_score(int cat, int score); - -// gain the victory achievements. Set 'hyper' to true for -// the Hyperstone victory, and false for the Orb of Yendor victory. -void achievement_victory(bool hyper); - -// gain the final achievements. Called with really=false whenever the user -// looks at their score, and really=true when the game really ends. -void achievement_final(bool really); - -// display the last achievement gained. -void achievement_display(); - -// call the achievement callbacks -void achievement_pump(); - -// achievements received this game -extern vector achievementsReceived; - // game forward declarations -bool mirrorkill(cell *c); -bool isNeighbor(cell *c1, cell *c2); -void checkTide(cell *c); namespace anticheat { extern bool tampered; } -int numplayers(); -void removeIvy(cell *c); -bool cellEdgeUnstable(cell *c, flagtype flags = 0); -int coastvalEdge(cell *c); #define HRANDMAX 0x7FFFFFFF -int hrandpos(); // 0 to HRANDMAX namespace rg { // possible parameters e.g. for restart_game and wrongmode @@ -908,42 +854,7 @@ namespace rg { static const char special_geometry = 'g'; } -int landMultiplier(eLand l); -eItem treasureType(eLand l); -void buildBarrier(cell *c, int d, eLand l = laNone); -void extendBarrier(cell *c); -bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr); -bool buildBarrier6(cellwalker cw, int type); -bool makeEmpty(cell *c); -bool isCrossroads(eLand l); enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMultiGo }; -void moveItem (cell *from, cell *to, bool activateYendor); -bool uncoverMines(cell *c, int lev, int dist, bool just_checking); -void killMonster(cell *c, eMonster who_killed, flagtype flags = 0); -void toggleGates(cell *ct, eWall type, int rad); -bool destroyHalfvine(cell *c, eWall newwall = waNone, int tval = 6); -void buildCrossroads2(cell *c); -bool isHaunted(eLand l); -heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special=0); -void setdist(cell *c, int d, cell *from); -void checkOnYendorPath(); -void killThePlayerAt(eMonster m, cell *c, flagtype flags); -bool notDippingFor(eItem i); -bool collectItem(cell *c2, bool telekinesis = false); -void castLightningBolt(cellwalker lig); -bool movepcto(int d, int subdir = 1, bool checkonly = false); -void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill = 0); -bool earthMove(cell *from, int dir); -void messageKill(eMonster killer, eMonster victim); -void moveMonster(cell *ct, cell *cf, int direction_hint); -int palaceHP(); -void placeLocalOrbs(cell *c); -int elementalKills(); -bool isMultitile(eMonster m); -void checkFreedom(cell *cf); -int rosedist(cell *c); -bool canPushStatueOn(cell *c); -void auto_teleport_charges(); namespace hive { void createBugArmy(cell *c); } namespace whirlpool { void generate(cell *wto); } @@ -971,8 +882,6 @@ struct movedir { cell *tgt; // for MD_USE_ORB: target cell }; -inline bool movepcto(const movedir& md) { return movepcto(md.d, md.subdir); } - void activateActiv(cell *c, bool msg); // shmup @@ -1114,90 +1023,15 @@ namespace shmup { void switch_shmup(); } -transmatrix& ggmatrix(cell *c); -transmatrix master_relative(cell *c, bool get_inverse = false); -void virtualRebase(cell*& base, transmatrix& at, bool tohex); -void virtualRebase(cell*& base, hyperpoint& h, bool tohex); -transmatrix calc_relative_matrix(cell *c, cell *c1, const hyperpoint& point_hint); -transmatrix calc_relative_matrix(cell *c, cell *c1, int direction_hint); - static const int NOHINT = -1; -// graph - -void showMissionScreen(); - -void restartGraph(); -void resetmusic(); - -void drawFlash(cell* c); -void drawBigFlash(cell* c); -void drawParticleSpeed(cell *c, color_t col, int speed); -void drawParticle(cell *c, color_t col, int maxspeed = 100); -void drawParticles(cell *c, color_t col, int qty, int maxspeed = 100); -void drawFireParticles(cell *c, int qty, int maxspeed = 100); - -int firecolor(int phase = 0, int mul = 1); - -void drawLightning(); -void drawSafety(); -void restartGraph(); -void movepckeydir(int); - -void centerpc(ld aspd); typedef color_t color_t; -void displayButton(int x, int y, const string& name, int key, int align, int rad = 0); -void displayColorButton(int x, int y, const string& name, int key, int align, int rad, color_t color, color_t color2 = 0); inline string ONOFF(bool b) { return XLAT(b ? "ON" : "OFF"); } -color_t darkened(color_t c); -extern int getcstat; -bool displaychr(int x, int y, int shift, int size, char chr, color_t col); -bool displayfr(int x, int y, int b, int size, const string &s, color_t color, int align); -bool displayfrSP(int x, int y, int sh, int b, int size, const string &s, color_t color, int align, int p); - -bool outofmap(hyperpoint h); -void applymodel(hyperpoint H, hyperpoint& Hscr); -void drawCircle(int x, int y, int size, color_t color, color_t fillcolor = 0); -void queuecircleat(cell *c, double rad, color_t col); -void fixcolor(int& col); -ld displayspin(cell *c, int d); -bool non_spatial_model(); -hyperpoint gethyper(ld x, ld y); -void resetview(); -void drawthemap(); -void drawfullmap(); -void draw_boundary(int w); -void draw_model_elements(); -extern function wrap_drawfullmap; -bool displaystr(int x, int y, int shift, int size, const char *str, color_t color, int align); -bool displaystr(int x, int y, int shift, int size, const string& str, color_t color, int align); - -extern int darken, inmirrorcount; -void calcparam(); - -#if CAP_SDL -color_t& qpixel(SDL_Surface *surf, int x, int y); -void setvideomode(); -#endif - -#if CAP_CONFIG -void saveConfig(); -#endif - -extern hyperpoint mouseh; - -extern hyperpoint ccenter; -extern ld crad; - -extern bool mousepressed, anyshiftclick, numlock_on; -extern string help; typedef function reaction_t; typedef function bool_reaction_t; -extern reaction_t help_delegate; - #define HELPFUN(x) (help_delegate = x, "HELPFUN") struct radarpoint { @@ -1212,9 +1046,6 @@ struct radarline { color_t line; }; -extern vector radarpoints; -extern vector radarlines; - extern vector< function > screens; template void pushScreen(const T& x) { screens.push_back(x); } @@ -1262,13 +1093,10 @@ extern display_data *current_display; #define gmatrix (current_display->cellmatrices) #define gmatrix0 (current_display->old_cellmatrices) -extern cell *mouseover, *mouseover2, *lmouseover; -extern string mouseovers; - -extern struct SDL_Surface *s; - typedef function cellfunction; +int coastvalEdge(cell *c); + namespace patterns { extern char whichShape; extern int canvasback; @@ -1547,14 +1375,6 @@ namespace polygonal { pair compute(ld x, ld y); } -void selectEyeGL(int ed); -void selectEyeMask(int ed); -extern int ticks; - -extern color_t backcolor, bordcolor, forecolor; - -void setGLProjection(color_t col = backcolor); - // passable flags #define P_MONSTER Flag(0) // can move through monsters @@ -1871,8 +1691,6 @@ extern int turncount; bool reduceOrbPower(eItem it, int cap); bool checkOrb(eMonster m1, eItem orb); -movedir vectodir(const hyperpoint& P); - namespace tortoise { extern int seekbits; int getRandomBits(); @@ -1893,26 +1711,9 @@ namespace sword { sworddir shift(cell *c1, cell *c2, sworddir); } -void killThePlayer(eMonster m, int id, flagtype flags); -bool attackJustStuns(cell *c2, flagtype flags, eMonster attacker); - -bool isTargetOrAdjacent(cell *c); -bool warningprotection(const string& s); -bool mineMarked(cell *c); -bool minesafe(); -bool hasSafeOrb(cell *c); -void placeWater(cell *c, cell *c2); -bool againstCurrent(cell *w, cell *from); -bool needConfirmation(); -bool needConfirmationEvenIfSaved(); - #define DEFAULTCONTROL (multi::players == 1 && !shmup::on && !multi::alwaysuse && !(rug::rugged && rug::renderonce)) #define DEFAULTNOR(sym) (DEFAULTCONTROL || multi::notremapped(sym)) -extern bool smooth_scrolling; -extern bool timerghost; -extern bool gen_wandering; - #define CAP_MENUSCALING (ISPANDORA || ISMOBILE) #if CAP_MENUSCALING @@ -1923,157 +1724,6 @@ extern bool gen_wandering; #define displayfrZH dialog::zoom::displayfr_highlight #endif -namespace dialog { - extern string highlight_text; - extern color_t dialogcolor; - extern int dfsize, dfspace; - - enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diIntSlider, diSlider, diBigItem, diKeyboard}; - - struct item { - tDialogItem type; - string body; - string value; - string keycaption; - int key; - color_t color, colorv, colork, colors, colorc; - int scale; - double param; - int p1, p2, p3; - int position; - }; - - struct scaler { - ld (*direct) (ld); - ld (*inverse) (ld); - bool positive; - }; - - static inline ld identity_f(ld x) { return x; }; - - const static scaler identity = {identity_f, identity_f, false}; - const static scaler logarithmic = {log, exp, true}; - const static scaler asinhic = {asinh, sinh, false}; - const static scaler asinhic100 = {[] (ld x) { return asinh(x*100); }, [] (ld x) { return sinh(x)/100; }, false}; - - struct numberEditor { - ld *editwhat; - string s; - ld vmin, vmax, step, dft; - string title, help; - scaler sc; - int *intval; ld intbuf; - bool animatable; - }; - - extern numberEditor ne; - - extern vector items; - - extern reaction_t reaction, extra_options, reaction_final; - - item& lastItem(); - extern color_t *palette; - - string keyname(int k); - - string disp(ld x); - void addSelItem(string body, string value, int key); - void addBoolItem(string body, bool value, int key); - void addBigItem(string body, int key); - void addColorItem(string body, int value, int key); - void openColorDialog(color_t& col, color_t *pal = palette); - extern bool colorAlpha; - void addHelp(string body); - void addInfo(string body, color_t color = dialogcolor); - void addItem(string body, int key); - void addKeyboardItem(string keys); - int addBreak(int val); - void addTitle(string body, color_t color, int scale); - - void init(); - void init(string title, color_t color = 0xE8E8E8, int scale = 150, int brk = 60); - void display(); - - void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help); - // step can be ld if we use scaleLog() - void editNumber(int& x, int vmin, int vmax, ld step, int dft, string title, string help); - void use_hexeditor(); - inline void scaleLog() { ne.sc = logarithmic; } - inline void scaleSinh() { ne.sc = asinhic; } - inline void scaleSinh100() { ne.sc = asinhic100; } - void bound_low(ld val); - void bound_up(ld val); - - void handleNavigation(int &sym, int &uni); - - namespace zoom { - bool displayfr(int x, int y, int b, int size, const string &s, color_t color, int align); - bool displayfr_highlight(int x, int y, int b, int size, const string &s, color_t color, int align, int hicolor = 0xFFFF00); - } - - bool editingDetail(); - - int handlePage(int& nl, int& nlm, int perpage); - void displayPageButtons(int i, bool pages); - bool handlePageButtons(int uni); - extern bool sidedialog; - extern int dialogflags; - extern int dcenter; - int displaycolor(color_t col); - - void openFileDialog(string& filename, string fcap, string ext, bool_reaction_t action); - - extern string infix; - bool hasInfix(const string &s); - bool editInfix(int uni); - - void vpush(color_t, const char *name); - extern vector > v; - - void addHelp(); - void addBack(); - void add_action(const reaction_t& action); - void add_key_action(int key, const reaction_t& action); - - void add_action_push(const reaction_t& action); - void addBoolItem_action(const string& s, bool& b, char c); - void addBoolItem_action_neg(const string& s, bool& b, char c); - template void addBoolItem_choice(const string& s, T& b, T val, char c) { - addBoolItem(s, b == val, c); - add_action([&b, val] { b = val; }); - } - - string view_edited_string(); - void start_editing(string& s); - string editchecker(int sym, int uni); - bool handle_edit_string(int sym, int uni, function checker = editchecker); - void edit_string(string& s, string title, string help); - - void confirm_dialog(const string& text, const reaction_t& act); - - inline void cheat_if_confirmed(const reaction_t& act) { - if(needConfirmationEvenIfSaved()) pushScreen([act] () { confirm_dialog(XLAT("This will enable the cheat mode, making this game ineligible for scoring. Are you sure?"), act); }); - else act(); - } - - inline void do_if_confirmed(const reaction_t& act) { - if(needConfirmationEvenIfSaved()) pushScreen([act] () { confirm_dialog(XLAT("This will end your current game and start a new one. Are you sure?"), act); }); - else act(); - } - - inline reaction_t add_confirmation(const reaction_t& act) { - return [act] { do_if_confirmed(act); }; - } - - extern int numberdark; - static const int DONT_SHOW = 16; - } - -void checkStunKill(cell *dest); - -void clearMessages(); - namespace shot { #if CAP_SHOT extern int shotx, shoty, shotformat; @@ -2367,6 +2017,8 @@ namespace anims { } #endif +extern bool timerghost; + namespace arg { #if CAP_COMMANDLINE @@ -2422,14 +2074,6 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASEFROM(2); #endif } -extern bool generatingEquidistant; - -void clearfrom(heptagon *at); -void clearHexes(heptagon *at); -void verifycells(heptagon *at); -int zebra40(cell *c); -cell *createMov(cell *c, int d); - #if CAP_TOUR namespace tour { extern bool on; @@ -2491,15 +2135,6 @@ namespace tour { } #endif -extern bool doCross; -void optimizeview(); - -extern bool noGUI; -extern bool dronemode; - -extern ld whatever[16]; -extern int whateveri[16]; - namespace sm { static const int NORMAL = 1; static const int MISSION = 2; @@ -2565,20 +2200,7 @@ namespace linepatterns { extern ld width; }; -transmatrix ddspin(cell *c, int d, ld bonus = 0); -transmatrix iddspin(cell *c, int d, ld bonus = 0); -bool doexiton(int sym, int uni); -void switchFullscreen(); -string turnstring(int i); static const int DISTANCE_UNKNOWN = 127; -int celldistance(cell *c1, cell *c2); -int hyperbolic_celldistance(cell *c1, cell *c2); -bool behindsphere(const transmatrix& V); -extern hyperpoint pirateCoords; - -bool mouseout(); - -bool againstWind(cell *c2, cell *c1); // to, from transmatrix atscreenpos(ld x, ld y, ld size); @@ -2613,8 +2235,6 @@ namespace inv { bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int ticks, bool hidden); -void initquickqueue(); -void quickqueue(); int darkenedby(int c, int lev); extern int mousex, mousey; #if CAP_MOUSEGRAB @@ -2795,8 +2415,6 @@ bool inmirror(eLand l); bool inmirror(cell *c); bool inmirror(const cellwalker& cw); -void queuemarkerat(const transmatrix& V, color_t col); - void check_total_victory(); void applyBoxNum(int& i, string name = ""); extern int hinttoshow; @@ -2925,8 +2543,6 @@ void modalDebug(cell *c); void push_debug_screen(); int getDistLimit(); -void drawqueue(); - #ifndef GL typedef float GLfloat; #endif @@ -3228,6 +2844,9 @@ struct hrmap_standard : hrmap { heptagon *create_step(heptagon *h, int direction) override; }; +void clearfrom(heptagon*); +void verifycells(heptagon*); + struct hrmap_hyperbolic : hrmap_standard { heptagon *origin; eVariation mvar; @@ -3580,11 +3199,6 @@ namespace texture { } #endif -dqi_line& queueline(const hyperpoint& H1, const hyperpoint& H2, color_t col, int prf = 0, PPR prio = PPR::LINE); - -dqi_action& queueaction(PPR prio, const reaction_t& action); -void queuereset(eModel m, PPR prio); - unsigned char& part(color_t& col, int i); transmatrix applyPatterndir(cell *c, const patterns::patterninfo& si); @@ -3690,50 +3304,7 @@ double randd(); transmatrix getOrientation(); #endif -bool showHalloween(); -extern bool havesave; -extern vector gamelog; -extern time_t savetime; -extern bool cblind; -extern void save_memory(); -namespace inv { void init(); } -extern bool survivalist; -extern bool hauntedWarning; -extern bool usedSafety; - namespace elec { extern int lightningfast; } -extern int lastkills; -extern map rosemap; -extern int hardcoreAt; -extern flagtype havewhat, hadwhat; -extern int safetyseed; -extern int lastsafety; -extern int knighted; -extern int rosephase; -extern int rosewave; -extern eItem localTreasureType(); -extern void clearshadow(); -extern bool seenSevenMines; -extern vector dcal; // queue for cpdist -extern vector pathq; // queue for pathdist -extern vector > butterflies; -extern vector crush_now, crush_next; -extern void shrand(int seed); -extern eLand safetyland; -extern int sagephase; -extern int lastsize; -extern int noiseuntil; -hyperpoint cpush0(int d, ld x); -inline hyperpoint xpush0(ld x) { return cpush0(0, x); } -inline hyperpoint ypush0(ld x) { return cpush0(1, x); } -transmatrix xspinpush(ld alpha, ld x); -hyperpoint xspinpush0(ld alpha, ld x); - -transmatrix cspin(int a, int b, ld alpha); -transmatrix cpush(int cid, ld alpha); - -bool eqmatrix(transmatrix A, transmatrix B, ld eps = 1e-2); -void set_column(transmatrix& T, int i, const hyperpoint& H); #define DF_INIT 1 // always display these #define DF_MSG 2 // always display these @@ -3761,63 +3332,11 @@ void set_column(transmatrix& T, int i, const hyperpoint& H); #define DEBBI(r,x) { if(debugflags & (r)) { println_log x; } } indenter_finish _debbi(debugflags & (r)); #endif -extern int debugflags; -int gmod(int i, int j); -int gdiv(int i, int j); -extern walltype winf[walltypes]; -extern vector land_tac; -string llts(long long i); -void clearMemoRPM(); -extern int randompattern[landtypes]; -extern int pair_to_vec(int x, int y); -typedef pair euc_pointer; -euc_pointer euclideanAt(int vec); -euc_pointer euclideanAtCreate(int vec); -bool isCyclic(eLand l); -bool generateAll(eLand l); -void extendcheck(cell *c); -void extendNowall(cell *c); -bool isbar4(cell *c); -void extendBarrierFront(cell *c); -void extendBarrierBack(cell *c); -void extendCR5(cell *c); - -bool mirrorwall(cell *c); -extern void setbarrier(cell *c); -extern function call_initgame; -extern void initializeCLI(); - -static const int max_vec = (1<<14); - -string helptitle(string s, color_t col); -pair cell_to_pair(cell *c); -extern bool nohud, nofps, nomap; - template array make_array(T a, T b, T c, T d) { array x; x[0] = a; x[1] = b; x[2] = c; x[3] = d; return x; } template array make_array(T a, T b, T c) { array x; x[0] = a; x[1] = b; x[2] = c; return x; } template array make_array(T a, T b) { array x; x[0] = a; x[1] = b; return x; } -extern cell *lastmountpos[MAXPLAYER]; - extern const hyperpoint Hypc; -ld det(const transmatrix& T); -void queuechr(const hyperpoint& h, int size, char chr, color_t col, int frame = 0); - -string fts(ld x, int prec = 6); -string fts_fixed(ld x, int prec = 6); - -bool model_needs_depth(); - -hyperpoint hpxy(ld x, ld y); -hyperpoint hpxy3(ld x, ld y, ld z); -ld sqhypot_d(int d, const hyperpoint& h); -ld hypot_d(int d, const hyperpoint& h); -ld dsqhypot_d(int d, const hyperpoint& a, const hyperpoint& b); -ld dhypot_d(int d, const hyperpoint& a, const hyperpoint& b); -transmatrix pushxto0(const hyperpoint& H); -transmatrix rpushxto0(const hyperpoint& H); -transmatrix spintox(const hyperpoint& H); -transmatrix ypush(ld alpha); #if CAP_SURFACE namespace surface { @@ -3841,13 +3360,6 @@ struct stringpar { stringpar(eItem i) { v= iinf[i].name; } }; -string XLAT(string x); -string XLAT(string x, stringpar p1); -string XLAT(string x, stringpar p1, stringpar p2); -string XLAT(string x, stringpar p1, stringpar p2, stringpar p3); -string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4); -string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4, stringpar p5); - namespace gp { typedef pair loc; @@ -3891,18 +3403,6 @@ namespace gp { extern string operation_name(); } -int get_sightrange(); -int get_sightrange_ambush(); - -int gamerange(); - -int numplayers(); - -bool has_nice_dual(); - -extern hyperpoint mid(const hyperpoint &h1, const hyperpoint &h2); -void loadNewConfig(FILE *f); - struct supersaver { string name; virtual string save() = 0; @@ -3916,8 +3416,6 @@ typedef vector> saverlist; extern saverlist savers; -string itsh(int i); - #if CAP_CONFIG template struct dsaver : supersaver { @@ -3992,6 +3490,10 @@ template<> struct saver : dsaver { void load(const string& s) { val = s; } }; +string fts(ld val, int prec); +string itsh(int x); +extern int debugflags; + template<> struct saver : dsaver { saver(ld& val) : dsaver(val) { } string save() { return fts(val, 10); } @@ -4002,20 +3504,6 @@ template<> struct saver : dsaver { }; #endif -extern vector> ptds; -extern ld intval(const hyperpoint &h1, const hyperpoint &h2); -transmatrix euscalezoom(hyperpoint h); -transmatrix euaffine(hyperpoint h); -transmatrix eupush(ld x, ld y); -transmatrix eupush3(ld x, ld y, ld z); -transmatrix eupush(hyperpoint h); -transmatrix rspintox(const hyperpoint& H); -transmatrix gpushxto0(const hyperpoint& H); -transmatrix build_matrix(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint h4); -hyperpoint normalize(hyperpoint H); -ld signum(ld x); - -extern ld hrandf(); namespace glhr { @@ -4098,12 +3586,6 @@ namespace glhr { void prepare(vector& v); } -void prettypoly(const vector& t, color_t fillcol, color_t linecol, int lev); -#if CAP_SHAPES -dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, PPR prio); -#endif -dqi_poly& queuetable(const transmatrix& V, const vector& f, int cnt, color_t linecol, color_t fillcol, PPR prio); - #if CAP_SHAPES struct floorshape; @@ -4134,8 +3616,6 @@ extern vector shPlainWall3D, shWireframe3D, shWall3D, shMiniWall3D; cell *newCell(int type, heptagon *master); extern color_t qpixel_pixel_outside; -void queuechr(int x, int y, int shift, int size, char chr, color_t col, int frame = 0, int align = 8); - int zebra3(cell *c); int geosupport_threecolor(); int geosupport_football(); @@ -4149,7 +3629,6 @@ int wallchance(cell *c, bool deepOcean); ld master_to_c7_angle(); -extern int mutantphase; void resize_screen_to(int x, int y); extern bool canvas_invisible; extern cell *pd_from; @@ -4265,14 +3744,6 @@ namespace gp { plainshape& get_plainshape(); } -#if CAP_SHAPES -dqi_poly& queuepoly(const transmatrix& V, const hpcshape& h, color_t col); -dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, PPR prio); -#endif - -void queuestr(const hyperpoint& h, int size, const string& chr, color_t col, int frame = 0); -void queuechr(const transmatrix& V, double size, char chr, color_t col, int frame = 0); - extern bool just_gmatrix; bool haveLeaderboard(int id); @@ -4712,51 +4183,6 @@ struct help_extension { extern vector help_extensions; -namespace gamestack { - bool pushed(); - void push(); - void pop(); - } - -namespace geom3 { - void switch_always3(); - void switch_fpp(); - void switch_tpp(); - } - -void queuestr(const transmatrix& V, double size, const string& chr, color_t col, int frame = 0, int align = 8); -void queuestr(int x, int y, int shift, int size, string str, color_t col, int frame = 0, int align = 8); - -ld frac(ld x); - -extern color_t poly_outline; - -extern std::mt19937 hrngen; - -bool anglestraight(cell *c, int d1, int d2); - -hyperpoint randomPointIn(int t); - -bool compute_relamatrix(cell *src, cell *tgt, int direction_hint, transmatrix& T); - -extern bool noshadow, bright, nohelp, dont_face_pc; -extern void switchHardcore(); - -extern bool shaderside_projection; - -namespace ors { - extern int mode; - extern string choices[]; - void show(); - void apply(); - void check_orientation(); - void unrotate(transmatrix& T); - void rerotate(transmatrix& T); - void reset(); - } - -bool saved_tortoise_on(cell *c); - #define RING(i) for(double i=0; i<=cgi.S84+1e-6; i+=SD3 * pow(.5, vid.linequality)) #define REVRING(i) for(double i=cgi.S84; i>=-1e-6; i-=SD3 * pow(.5, vid.linequality)) #define PRING(i) for(double i=0; i<=cgi.S84+1e-6; i+= pow(.5, vid.linequality)) @@ -4902,22 +4328,6 @@ namespace crystal { #endif } -hyperpoint get_warp_corner(cell *c, int cid); -hyperpoint get_corner_position(cell *c, int cid, ld cf = 3); - -int decodeId(heptagon* h); -heptagon* encodeId(int id); - -void virtualRebaseSimple(heptagon*& base, transmatrix& at); - -extern bool game_active, playerfound; - -string bygen(reaction_t h); - -#if CAP_URL -void open_url(string s); -#endif - // HyperRogue streams struct hstream { @@ -5044,7 +4454,7 @@ void for_each_in_tuple(std::tuple const& t, F f) inline void print(hstream& hs, const string& s) { hs.write_chars(s.c_str(), isize(s)); } inline void print(hstream& hs, int i) { print(hs, its(i)); } -inline void print(hstream& hs, ld x) { print(hs, fts(x)); } +inline void print(hstream& hs, ld x) { print(hs, fts(x, 6)); } inline void print(hstream& hs, color_t col) { print(hs, itsh8(col)); } template void print(hstream& hs, const walker& w) { print(hs, "[", w.at, "/", w.spin, "/", w.mirrored, "]"); } @@ -5128,61 +4538,6 @@ struct indenter_finish : indenter { ~indenter_finish() { if(hlog.indentation != ind.backup) println(hlog, "(done)"); } }; -void appendHelp(string s); - -transmatrix rspintox(const hyperpoint& H); - -extern bool playermoved; - -extern int tidalsize; -extern void calcTidalPhase(); - -void curvepoint(const hyperpoint& H1); -dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio); -void queueball(const transmatrix& V, ld rad, color_t col, eItem what); - -ld cos_auto(ld x); -ld sin_auto(ld x); -ld tan_auto(ld x); -ld asin_auto(ld x); -ld atan_auto(ld x); -ld atan2_auto(ld x); -ld atan2(hyperpoint h); - -namespace anims { - #if CAP_ANIMATIONS - void apply(); - void rollback(); - void show(); - bool any_on(); - bool any_animation(); - bool center_music(); - - extern string animfile; - - extern int noframes; - extern ld period, cycle_length, parabolic_length, rug_angle, circle_radius, circle_spins; - #else - static bool any_on() { return false; } - static void rollback() { } - static bool center_music() { return false; } - static bool any_animation() { return false; } - static void apply() { } - #endif - } - -#if CAP_STARTANIM -namespace startanims { - extern reaction_t current; - void pick(); - } -#endif - -extern int animation_lcm; -extern ld animation_factor; -ld parseld(const string& s); -pair vec_to_pair(int vec); - struct bignum { static const int BASE = 1000000000; static const long long BASE2 = BASE * (long long)BASE; @@ -5289,10 +4644,6 @@ namespace ts { cell *child_number(cell *c, int id, const cellfunction& cf); } -void generate_around(cell *c); -int euclidAlt(short x, short y); -int cylinder_alt(cell *c); - struct exp_parser { string s; int at; @@ -5339,41 +4690,10 @@ namespace brownian { #define ONEMPTY if(d == 7 && passable(c, NULL, 0) && !safety && !reptilecheat) -extern bool reptilecheat; - -void enable_cheat(); - -extern int cells_drawn; - void menuitem_sightrange(char c = 'r'); -bool point_behind(const hyperpoint h); -bool invalid_point(const hyperpoint h); -bool invalid_point(const transmatrix T); -bool in_smart_range(const transmatrix& T); - -void curvepoint(const hyperpoint& H1); -dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio); - -bool haveaura(); - -string parser_help(); - static const ld degree = M_PI / 180; -void show_color_dialog(); - -extern ld band_shift; - -int cone_side(const hyperpoint H); - -void fix_the_band(transmatrix& T); - -struct bandfixer { - dynamicval bw; - bandfixer(transmatrix& T) : bw(band_shift, band_shift) { fix_the_band(T); } - }; - extern unordered_map params; namespace dq { @@ -5386,66 +4706,6 @@ namespace dq { void enqueue_by_matrix(heptagon *h, const transmatrix& T); } -typedef pair named_functionality; -inline named_functionality named_dialog(string x, reaction_t dialog) { return named_functionality(x, [dialog] () { pushScreen(dialog); }); } - -extern hookset *hooks_o_key; - -named_functionality get_o_key(); - -hyperpoint nearcorner(cell *c, int i); -extern bool showquotients; - -bool do_draw(cell *c, const transmatrix& T); -ld sintick(int period, ld phase = 0); - -#if CAP_RACING -namespace racing { - extern bool on, player_relative, track_ready, guiding, standard_centering; - extern ld race_advance, race_angle; - extern int ghosts_to_show, ghosts_to_save; - void generate_track(); - void configure_race(); - void prepare_subscreens(); - extern vector track; - extern int current_player; - extern vector race_lands; - extern string track_code; - extern int race_start_tick, race_finish_tick[MAXPLAYER]; - void race_won(); - void apply_seed(); - string racetimeformat(int t); - void add_debug(cell *c); - void displayScore(eLand l); - } - -#else - -// static bool on = false: emits a warning -// static const bool on = false: no warning, but does not allow assignment - -namespace racing { - static const always_false on; - } - -inline bool subscreen_split(reaction_t for_each_subscreen) { return false; } -#endif - -bool in_gravity_zone(cell *c); -bool normal_gravity_at(cell *c); - -void build_pool(cell *c, bool with_boat); -void createArrowTrapAt(cell *c, eLand land); -bool no_barriers_in_radius(cell *c, int rad); -bool in_full_game(); - -extern ld extra_generation_distance; - -namespace subscreens { - void prepare(); - bool split(reaction_t for_each_subscreen); - } - template void texture_order(const T& f) { const int STEP = vid.texture_step; const ld STEP2 = STEP; @@ -5464,45 +4724,6 @@ template void texture_order(const T& f) { } } -void set_euland3(cell *c, int co0, int co1, int alt, int hash); - -extern bool first_cell_to_draw; -extern int current_rbuffer; -extern bool new_projection_needed; -inline void reset_projection() { new_projection_needed = true; } -extern ld ptick(int period, ld phase = 0); -void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& V2, const hyperpoint h2, color_t col, int prec); -void gridline(const transmatrix& V, const hyperpoint h1, const hyperpoint h2, color_t col, int prec); - -static const int POLY_DRAWLINES = 1; // draw the lines -static const int POLY_DRAWAREA = 2; // draw the area -static const int POLY_INVERSE = 4; // draw the inverse -- useful in stereographic projection -static const int POLY_ISSIDE = 8; // never draw in inverse -static const int POLY_BEHIND = 16; // there are points behind the camera -static const int POLY_TOOLARGE = 32; // some coordinates are too large -- best not to draw to avoid glitches -static const int POLY_INFRONT = 64; // on the sphere (orthogonal projection), do not draw without any points in front -static const int POLY_HASWALLS = 128; // floor shapes which have their sidewalls -static const int POLY_PLAIN = 256; // plain floors -static const int POLY_FULL = 512; // full floors -static const int POLY_HASSHADOW = 1024; // floor shapes which have their shadows, or can use shFloorShadow -static const int POLY_GP = 2048; // Goldberg shapes -static const int POLY_VCONVEX = 4096; // Convex shape (vertex) -static const int POLY_CCONVEX = 8192; // Convex shape (central) -static const int POLY_CENTERIN = 16384; // new system of side checking -static const int POLY_FORCEWIDE = (1<<15); // force wide lines -static const int POLY_NOTINFRONT = (1<<16); // points not in front -static const int POLY_NIF_ERROR = (1<<17); // points moved to the outline cross the image, disable -static const int POLY_BADCENTERIN = (1<<18); // new system of side checking -static const int POLY_PRECISE_WIDE = (1<<19); // precise width calculation -static const int POLY_FORCE_INVERTED = (1<<20); // force inverted -static const int POLY_ALWAYS_IN = (1<<21); // always draw this -static const int POLY_TRIANGLES = (1<<22); // made of TRIANGLES, not TRIANGLE_FAN -static const int POLY_INTENSE = (1<<23); // extra intense colors -static const int POLY_DEBUG = (1<<24); // debug this shape - -void pregen(); -extern vector currentlands; - struct gamedata { // important parameters should be visible eGeometry geo; @@ -5538,92 +4759,42 @@ extern eLastmovetype lastmovetype, nextmovetype; enum eForcemovetype { fmSkip, fmMove, fmAttack, fmInstant, fmActivate }; extern eForcemovetype forcedmovetype; -extern hookset *hooks_gamedata; - -namespace dual { - // 0 = dualmode off, 1 = in dualmode (no game chosen), 2 = in dualmode (working on one of subgames) - extern int state; - extern int currently_loaded, main_side; - extern bool affect_both; - - bool movepc(int d, int subdir, bool checkonly); - extern transmatrix player_orientation[2]; - - void add_choice(); - - bool split(reaction_t what); - void split_or_do(reaction_t what); - bool may_split(reaction_t what); - void may_split_or_do(reaction_t what); - void switch_to(int i); - void in_subscreen(reaction_t what); - - bool check_side(eLand l); - void assign_landsides(); - - void disable(); - void enable(); - - transmatrix get_orientation(); - - inline reaction_t mayboth(reaction_t what) { return [=] { may_split_or_do(what); }; } - } - -void raise_error(); -bool invalid_matrix(const transmatrix T); - -extern bool show_memory_warning; -extern bool ignored_memory_warning; -extern int reserve_count, reserve_limit; -void apply_memory_reserve(); -void show_memory_menu(); static const int PSEUDOKEY_MEMORY = 16397; static const color_t NOCOLOR = 0; -extern int global_projection; -void spinEdge(ld aspd); - -inline hyperpoint cpush0(int c, ld x) { - hyperpoint h = Hypc; - h[GDIM] = cos_auto(x); - h[c] = sin_auto(x); - return h; - } - -inline hyperpoint xspinpush0(ld alpha, ld x) { - hyperpoint h = Hypc; - h[GDIM] = cos_auto(x); - h[0] = sin_auto(x) * cos(alpha); - h[1] = sin_auto(x) * -sin(alpha); - return h; - } - -extern renderbuffer *floor_textures; - -int wingphase(int period, int phase = 0); - -void queuecircle(int x, int y, int size, color_t color, PPR prio = PPR::CIRCLE, color_t fillcolor = 0); - -#if CAP_BT -namespace kite { - hrmap *new_map(); - void find_cell_connection(cell *c, int d); - enum pshape {pDart, pKite}; - pshape getshape(heptagon *h); - pair>, vector>> make_walls(); - hyperpoint get_corner(cell *c, int d, ld cf); - } -#endif - -bool in_perspective(); - -extern int noclipped; -void draw_radar(bool cornermode); -namespace binary { int updir(); } + typedef pair euc_pointer; + static const int max_vec = (1<<14); + extern bool needConfirmationEvenIfSaved(); #define EX #define EXT(z) } +#define IS(z) = z #include "autohdr.h" +#undef IS +#define IS(z) + +namespace hr { + inline bool movepcto(const movedir& md) { return movepcto(md.d, md.subdir); } + + inline hyperpoint cpush0(int c, ld x) { + hyperpoint h = Hypc; + h[GDIM] = cos_auto(x); + h[c] = sin_auto(x); + return h; + } + + inline hyperpoint xspinpush0(ld alpha, ld x) { + hyperpoint h = Hypc; + h[GDIM] = cos_auto(x); + h[0] = sin_auto(x) * cos(alpha); + h[1] = sin_auto(x) * -sin(alpha); + return h; + } + + inline hyperpoint xpush0(ld x) { return cpush0(0, x); } + inline hyperpoint ypush0(ld x) { return cpush0(1, x); } + inline void reset_projection() { new_projection_needed = true; } + } diff --git a/hyperpoint.cpp b/hyperpoint.cpp index d4b59bbf..56c48d06 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -36,11 +36,11 @@ ld inverse_tanh(ld x) { return log((1+x)/(1-x)) / 2; } */ #define M_PI 3.14159265358979 #endif -ld squar(ld x) { return x*x; } +EX ld squar(ld x) { return x*x; } -int sig(int z) { return (sphere || sol || z eps) @@ -326,7 +326,7 @@ bool eqmatrix(transmatrix A, transmatrix B, ld eps) { #if MAXMDIM >= 4 // in the 3D space, move the point h orthogonally to the (x,y) plane by z units -hyperpoint orthogonal_move(const hyperpoint& h, ld z) { +EX hyperpoint orthogonal_move(const hyperpoint& h, ld z) { if(!hyperbolic) return rgpushxto0(h) * cpush(2, z) * C0; if(nil) return nisot::translate(h) * cpush0(2, z); if(translatable) return hpxy3(h[0], h[1], h[2] + z); @@ -338,11 +338,11 @@ hyperpoint orthogonal_move(const hyperpoint& h, ld z) { #endif // push alpha units vertically -transmatrix ypush(ld alpha) { return cpush(1, alpha); } +EX transmatrix ypush(ld alpha) { return cpush(1, alpha); } -transmatrix zpush(ld z) { return cpush(2, z); } +EX transmatrix zpush(ld z) { return cpush(2, z); } -transmatrix matrix3(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i) { +EX transmatrix matrix3(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i) { #if MAXMDIM==3 return transmatrix {{{a,b,c},{d,e,f},{g,h,i}}}; #else @@ -353,7 +353,7 @@ transmatrix matrix3(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i) { #endif } -transmatrix matrix4(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i, ld j, ld k, ld l, ld m, ld n, ld o, ld p) { +EX transmatrix matrix4(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i, ld j, ld k, ld l, ld m, ld n, ld o, ld p) { #if MAXMDIM==3 return transmatrix {{{a,b,d},{e,f,h},{m,n,p}}}; #else @@ -362,7 +362,7 @@ transmatrix matrix4(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i, ld j, } #if MAXMDIM >= 4 -void swapmatrix(transmatrix& T) { +EX void swapmatrix(transmatrix& T) { for(int i=0; i<4; i++) swap(T[i][2], T[i][3]); for(int i=0; i<4; i++) swap(T[2][i], T[3][i]); if(DIM == 3) { @@ -373,12 +373,12 @@ void swapmatrix(transmatrix& T) { for(int i=0; i<4; i++) for(int j=0; j<4; j++) if(isnan(T[i][j])) T = Id; } -void swapmatrix(hyperpoint& h) { +EX void swapmatrix(hyperpoint& h) { swap(h[2], h[3]); } #endif -transmatrix parabolic1(ld u) { +EX transmatrix parabolic1(ld u) { if(euclid) return ypush(u); else { @@ -391,7 +391,7 @@ transmatrix parabolic1(ld u) { } } -transmatrix parabolic13(ld u, ld v) { +EX transmatrix parabolic13(ld u, ld v) { if(euclid) return ypush(u); else { @@ -405,7 +405,7 @@ transmatrix parabolic13(ld u, ld v) { } } -transmatrix spintoc(const hyperpoint& H, int t, int f) { +EX transmatrix spintoc(const hyperpoint& H, int t, int f) { transmatrix T = Id; ld R = hypot(H[f], H[t]); if(R >= 1e-12) { @@ -415,7 +415,7 @@ transmatrix spintoc(const hyperpoint& H, int t, int f) { return T; } -transmatrix rspintoc(const hyperpoint& H, int t, int f) { +EX transmatrix rspintoc(const hyperpoint& H, int t, int f) { transmatrix T = Id; ld R = hypot(H[f], H[t]); if(R >= 1e-12) { @@ -426,18 +426,18 @@ transmatrix rspintoc(const hyperpoint& H, int t, int f) { } // rotate the hyperbolic plane around C0 such that H[1] == 0 and H[0] >= 0 -transmatrix spintox(const hyperpoint& H) { +EX transmatrix spintox(const hyperpoint& H) { if(GDIM == 2) return spintoc(H, 0, 1); transmatrix T1 = spintoc(H, 0, 1); return spintoc(T1*H, 0, 2) * T1; } -void set_column(transmatrix& T, int i, const hyperpoint& H) { +EX void set_column(transmatrix& T, int i, const hyperpoint& H) { for(int j=0; j0?1:0; } +EX ld signum(ld x) { return x<0?-1:x>0?1:0; } bool asign(ld y1, ld y2) { return signum(y1) != signum(y2); } ld xcross(ld x1, ld y1, ld x2, ld y2) { return x1 + (x2 - x1) * y1 / (y1 - y2); } -transmatrix solmul(const transmatrix T, const transmatrix V) { +EX transmatrix solmul(const transmatrix T, const transmatrix V) { if(nonisotropic) return nisot::transport_view(T, V); else return T * V; } -transmatrix solmul_pt(const transmatrix Position, const transmatrix T) { +EX transmatrix solmul_pt(const transmatrix Position, const transmatrix T) { if(nonisotropic) return nisot::parallel_transport(Position, T); else return Position * T; } -transmatrix spin_towards(const transmatrix Position, const hyperpoint goal, int dir, int back) { +EX transmatrix spin_towards(const transmatrix Position, const hyperpoint goal, int dir, int back) { transmatrix T = nonisotropic ? nisot::spin_towards(Position, goal) : rspintox(inverse(Position) * goal); @@ -796,7 +796,7 @@ transmatrix spin_towards(const transmatrix Position, const hyperpoint goal, int return T; } -ld ortho_error(transmatrix T) { +EX ld ortho_error(transmatrix T) { ld err = 0; diff --git a/hyperweb.cpp b/hyperweb.cpp index 93d92f27..fb94eda1 100644 --- a/hyperweb.cpp +++ b/hyperweb.cpp @@ -54,12 +54,13 @@ namespace hr { // -- demo -- -void open_url(string s) { +#if CAP_URL +EX void open_url(string s) { EM_ASM_({ window.open(UTF8ToString($0, 1000)); }, s.c_str()); } - +#endif // window.open(Pointer_stringify($0)); bool demoanim; diff --git a/hypgraph.cpp b/hypgraph.cpp index b5cc1443..f76919c8 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -22,7 +22,7 @@ void camrotate(ld& hx, ld& hy) { hyperpoint perspective_to_space(hyperpoint h, ld alpha = vid.alpha, eGeometryClass geo = ginf[geometry].cclass); -bool non_spatial_model() { +EX bool non_spatial_model() { if(among(pmodel, mdRotatedHyperboles, mdJoukowsky, mdJoukowskyInverted, mdPolygonal, mdPolynomial)) return true; if(pmodel == mdSpiral && euclid) @@ -78,7 +78,7 @@ hyperpoint space_to_perspective(hyperpoint z, ld alpha) { return z; } -hyperpoint gethyper(ld x, ld y) { +EX hyperpoint gethyper(ld x, ld y) { ld hx = (x - current_display->xcenter) / current_display->radius; ld hy = (y - current_display->ycenter) / current_display->radius / vid.stretch; @@ -163,7 +163,7 @@ ld get_tz(hyperpoint H) { return tz; } -ld atan2(hyperpoint h) { +EX ld atan2(hyperpoint h) { return atan2(h[1], h[0]); } @@ -302,7 +302,7 @@ hyperpoint compute_hybrid(hyperpoint H, int rootid) { return ret; } -void applymodel(hyperpoint H, hyperpoint& ret) { +EX void applymodel(hyperpoint H, hyperpoint& ret) { hyperpoint H_orig = H; @@ -764,12 +764,12 @@ void applymodel(hyperpoint H, hyperpoint& ret) { // game-related graphics -transmatrix sphereflip; // on the sphere, flip -bool playerfound; // has player been found in the last drawing? +EX transmatrix sphereflip; // on the sphere, flip +EX bool playerfound; // has player been found in the last drawing? double q3 = sqrt(double(3)); -bool outofmap(hyperpoint h) { +EX bool outofmap(hyperpoint h) { if(GDIM == 3) return false; else if(euclid) @@ -807,7 +807,7 @@ double zgrad0(double l1, double l2, int nom, int den) { return lev_to_factor(l1 + (l2-l1) * nom / den); } -bool behindsphere(const hyperpoint& h) { +EX bool behindsphere(const hyperpoint& h) { if(!sphere) return false; if(mdBandAny()) return false; @@ -843,7 +843,7 @@ ld spherity(const hyperpoint& h) { return 1; } -bool behindsphere(const transmatrix& V) { +EX bool behindsphere(const transmatrix& V) { return behindsphere(tC0(V)); } @@ -879,7 +879,7 @@ transmatrix actualV(const heptspin& hs, const transmatrix& V) { return (hs.spin || !BITRUNCATED) ? V * spin(hs.spin*2*M_PI/S7 + master_to_c7_angle()) : V; } -bool point_behind(hyperpoint h) { +EX bool point_behind(hyperpoint h) { if(sphere) return false; if(!in_perspective()) return false; if(pmodel == mdGeodesic) h = nisot::inverse_exp(h, nisot::iLazy); @@ -891,7 +891,7 @@ void raise_error() { println(hlog, "something wrong"); } -bool invalid_matrix(const transmatrix T) { +EX bool invalid_matrix(const transmatrix T) { for(int i=0; i 1e8 || T[i][j] < -1e8 || std::isinf(T[i][j])) return true; @@ -899,11 +899,11 @@ bool invalid_matrix(const transmatrix T) { return true; } -bool invalid_point(const hyperpoint h) { +EX bool invalid_point(const hyperpoint h) { return std::isnan(h[DIM]) || h[DIM] > 1e8 || std::isinf(h[DIM]); } -bool in_smart_range(const transmatrix& T) { +EX bool in_smart_range(const transmatrix& T) { hyperpoint h = tC0(T); if(invalid_point(h)) return false; if(nil) return true; @@ -1176,7 +1176,7 @@ transmatrix eumovedir(int d) { return eumove(0,0); } -void spinEdge(ld aspd) { +EX void spinEdge(ld aspd) { ld downspin = 0; if(dual::state == 2 && dual::currently_loaded != dual::main_side) { transmatrix our = dual::get_orientation(); @@ -1223,7 +1223,7 @@ void spinEdge(ld aspd) { View = spin(downspin) * View; } -void centerpc(ld aspd) { +EX void centerpc(ld aspd) { if(subscreens::split([=] () {centerpc(aspd);})) return; if(dual::split([=] () { centerpc(aspd); })) return; @@ -1307,7 +1307,7 @@ void centerpc(ld aspd) { ors::rerotate(cwtV); ors::rerotate(View); } -void optimizeview() { +EX void optimizeview() { if(subscreens::split(optimizeview)) return; if(dual::split(optimizeview)) return; @@ -1392,7 +1392,7 @@ void ballgeometry() { queuereset(pmodel, PPR::CIRCLE); } -void resetview() { +EX void resetview() { DEBBI(DF_GRAPH, ("reset view")); View = conformal::rotmatrix(); // EUCLIDEAN @@ -1412,9 +1412,9 @@ void panning(hyperpoint hf, hyperpoint ht) { playermoved = false; } -int cells_drawn, cells_generated; +EX int cells_drawn, cells_generated; -void fullcenter() { +EX void fullcenter() { conformal::path_for_lineanimation.clear(); if(playerfound && false) centerpc(INF); else { @@ -1434,7 +1434,7 @@ transmatrix screenpos(ld x, ld y) { return V; } -transmatrix atscreenpos(ld x, ld y, ld size) { +EX transmatrix atscreenpos(ld x, ld y, ld size) { transmatrix V = Id; if(pmodel == mdFlatten) { @@ -1481,7 +1481,7 @@ color_t ringcolor = darkena(0xFF, 0, 0xFF); color_t modelcolor = 0; #if CAP_QUEUE -void draw_model_elements() { +EX void draw_model_elements() { dynamicval lw(vid.linewidth, vid.linewidth * vid.multiplier_ring); switch(pmodel) { @@ -1602,7 +1602,7 @@ void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { } */ } -void draw_boundary(int w) { +EX void draw_boundary(int w) { if(w == 1) return; if(nonisotropic || euclid) return; @@ -1802,8 +1802,8 @@ void draw_boundary(int w) { } #endif -ld band_shift = 0; -void fix_the_band(transmatrix& T) { +EX ld band_shift = 0; +EX void fix_the_band(transmatrix& T) { if(((models[pmodel].flags & mf::quasiband) && T[DIM][DIM] > 1e6) || (sphere && pmodel == mdSpiral)) { hyperpoint H = tC0(T); find_zlev(H); @@ -1822,6 +1822,13 @@ void fix_the_band(transmatrix& T) { } } +#if HDR +struct bandfixer { + dynamicval bw; + bandfixer(transmatrix& T) : bw(band_shift, band_shift) { fix_the_band(T); } + }; +#endif + namespace dq { queue> drawqueue; @@ -1844,7 +1851,7 @@ namespace dq { #endif } -bool do_draw(cell *c) { +EX bool do_draw(cell *c) { // do not display out of range cells, unless on torus if(c->pathdist == PINFD && geometry != gTorus && vid.use_smart_range == 0) return false; @@ -1856,7 +1863,7 @@ bool do_draw(cell *c) { return true; } -ld extra_generation_distance = 99; +EX ld extra_generation_distance = 99; // returns false if limited bool limited_generation(cell *c) { @@ -1867,7 +1874,7 @@ bool limited_generation(cell *c) { return true; } -bool do_draw(cell *c, const transmatrix& T) { +EX bool do_draw(cell *c, const transmatrix& T) { PROD( if(product::pmap) return product::in_actual([&] { return do_draw(product::get_at(c, product::plevel), T); }); ) if(WDIM == 3) { @@ -1917,7 +1924,7 @@ bool do_draw(cell *c, const transmatrix& T) { return true; } -int cone_side(const hyperpoint H) { +EX int cone_side(const hyperpoint H) { hyperpoint ret; if(hyperbolic) makeband(H, ret, band_conformal); else ret = H; diff --git a/init.cpp b/init.cpp index bc1e5e30..6a76bc27 100644 --- a/init.cpp +++ b/init.cpp @@ -6,18 +6,18 @@ namespace hr { #if CU_INIT -int fontscale = 100; +EX int fontscale = 100; -int debugflags = DF_INIT | DF_ERROR | DF_WARN | DF_MSG | DF_TIME | DF_LOG; +EX int debugflags = DF_INIT | DF_ERROR | DF_WARN | DF_MSG | DF_TIME | DF_LOG; string s0; -bool fixseed = false; -int startseed = 0; +EX bool fixseed = false; +EX int startseed = 0; eLand firstland0; -void initAll() { +EX void initAll() { init_floorcolors(); showstartmenu = true; ca::init(); @@ -50,7 +50,7 @@ void initAll() { polygonal::solve(); } -void finishAll() { +EX void finishAll() { achievement_final(!items[itOrbSafety]); #if CAP_SAVE diff --git a/landgen.cpp b/landgen.cpp index 825e5b9f..237a8822 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -6,14 +6,14 @@ namespace hr { // land generation routines -bool safety = false; +EX bool safety = false; eLand lastland; int lastexplore; bool randomPatternsMode = false; -int randompattern[landtypes]; +EX int randompattern[landtypes]; int genrange_bonus = 0; @@ -25,7 +25,7 @@ void doOvergenerate() { setdist(playerpos(i), 7 - getDistLimit() - genrange_bonus, NULL); } -bool notDippingFor(eItem i) { +EX bool notDippingFor(eItem i) { if(peace::on) return false; if(chaosmode > 1) return true; int v = items[i] - currentLocalTreasure; @@ -58,7 +58,7 @@ void buildRedWall(cell *c, int gemchance) { #define RANDPAT3(i) (randpatternMajority(c,i,RANDITER)) #define RANDPATV(x) (randpattern(c,randompattern[x])) -bool reptilecheat = false; +EX bool reptilecheat = false; bool blizzard_no_escape1(cell *c, manual_celllister &cl) { if(!cl.add(c)) return true; @@ -111,7 +111,7 @@ eMonster genRuinMonster(cell *c) { void gen_brownian(cell *c); -void createArrowTrapAt(cell *c, eLand land) { +EX void createArrowTrapAt(cell *c, eLand land) { cellwalker cw(c, hrand(c->type)); cell* cc[5]; cc[2] = c; @@ -137,7 +137,7 @@ void createArrowTrapAt(cell *c, eLand land) { } } -void build_pool(cell *c, bool with_boat) { +EX void build_pool(cell *c, bool with_boat) { bool vacant = true; if(c->monst || !among(c->wall, waNone, waSea, waBoat)) vacant = false; forCellCM(c1, c) if(!among(c1->land, laNone, laVariant) || c1->monst || !among(c1->wall, waNone, waSea, waBoat)) vacant = false; @@ -148,14 +148,15 @@ void build_pool(cell *c, bool with_boat) { } } -void place_elemental_wall(cell *c) { +EX void place_elemental_wall(cell *c) { if(c->land == laEFire) c->wall = waEternalFire; else if(c->land == laEWater) c->wall = waSea; else if(c->land == laEAir) c->wall = waChasm; else if(c->land == laEEarth) c->wall = waStone; } -int hrand_monster(int x) { +// automatically adjust monster generation for 3D geometries +EX int hrand_monster(int x) { // dual geometry mode is much harder, so generate less monsters to balance it if(dual::state) x *= 3; // in 3D monster generation depends on the sight range @@ -166,7 +167,7 @@ int hrand_monster(int x) { return hrand(x); } -void giantLandSwitch(cell *c, int d, cell *from) { +EX void giantLandSwitch(cell *c, int d, cell *from) { bool fargen = d == min(BARLEV, 9); switch(c->land) { @@ -2460,7 +2461,7 @@ void giantLandSwitch(cell *c, int d, cell *from) { // repair the buggy walls flowing in from another land, like ice walls flowing into the Caves -void repairLandgen(cell *c) { +EX void repairLandgen(cell *c) { if(c->land == laCaves && c->wall != waCavewall && c->wall != waCavefloor) c->wall = waCavefloor; @@ -2512,7 +2513,7 @@ void repairLandgen(cell *c) { } } -void setland_randomwalk(cell *c) { +EX void setland_randomwalk(cell *c) { if(c->land) return; if(hrand(10) == 0) setland(c, currentlands[hrand(isize(currentlands))]); else { @@ -2522,7 +2523,7 @@ void setland_randomwalk(cell *c) { } } -void setdist(cell *c, int d, cell *from) { +EX void setdist(cell *c, int d, cell *from) { if(c->mpdist <= d) return; if(c->mpdist > d+1 && d < BARLEV) setdist(c, d+1, from); diff --git a/landlock.cpp b/landlock.cpp index cc3879f1..0c2166e1 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -26,7 +26,7 @@ int isNative(eLand l, eMonster m) { return false; } -eItem treasureType(eLand l) { return linf[l].treasure; } +EX eItem treasureType(eLand l) { return linf[l].treasure; } eItem treasureTypeUnlock(eLand l, eItem u) { if(u != itOrbLove && l == laPrincessQuest) @@ -39,25 +39,25 @@ eLand landof(eItem it) { return laNone; } -int landMultiplier(eLand l) { +EX int landMultiplier(eLand l) { if(l == laCamelot || l == laPrincessQuest) return 10; return 1; } -bool isCrossroads(eLand l) { +EX bool isCrossroads(eLand l) { return l == laCrossroads || l == laCrossroads2 || l == laCrossroads3 || l == laCrossroads4 || l == laCrossroads5; } -bool bearsCamelot(eLand l) { +EX bool bearsCamelot(eLand l) { return isCrossroads(l) && l != laCrossroads2 && l != laCrossroads5; } -bool inmirror(const cellwalker& cw) { +EX bool inmirror(const cellwalker& cw) { return inmirror(cw.at->land); } -eLand oppositeElement(eLand l, eLand l2) { +EX eLand oppositeElement(eLand l, eLand l2) { if(l == laEFire) return laEWater; if(l == laEWater) return laEFire; if(l == laEAir) return laEEarth; diff --git a/language.cpp b/language.cpp index a1a05c9e..0d26836a 100644 --- a/language.cpp +++ b/language.cpp @@ -7,10 +7,10 @@ namespace hr { -const char *dnameof(eMonster m) { return minf[m].name; } -const char *dnameof(eLand l) { return linf[l].name; } -const char *dnameof(eWall w) { return winf[w].name; } -const char *dnameof(eItem i) { return iinf[i].name; } +EX const char *dnameof(eMonster m) { return minf[m].name; } +EX const char *dnameof(eLand l) { return linf[l].name; } +EX const char *dnameof(eWall w) { return winf[w].name; } +EX const char *dnameof(eItem i) { return iinf[i].name; } /* string dnameofEnum(eItem i) { @@ -112,13 +112,9 @@ string choose4(int g, string a, string b, string c, string d) { return "unknown genus"; } -int playergender(); -int princessgender(); -int lang(); - set warnshown; -void basicrep(string& x) { +void basicrep(string& x) { #if CAP_TRANS const sentence *s = findInHashTable(x, all_sentences); @@ -324,25 +320,25 @@ void parrep(string& x, string w, stringpar p) { void postrep(string& s) { } -string XLAT(string x) { +EX string XLAT(string x) { basicrep(x); postrep(x); return x; } -string XLAT(string x, stringpar p1) { +EX string XLAT(string x, stringpar p1) { basicrep(x); parrep(x,"1",p1.v); postrep(x); return x; } -string XLAT(string x, stringpar p1, stringpar p2) { +EX string XLAT(string x, stringpar p1, stringpar p2) { basicrep(x); parrep(x,"1",p1.v); parrep(x,"2",p2.v); postrep(x); return x; } -string XLAT(string x, stringpar p1, stringpar p2, stringpar p3) { +EX string XLAT(string x, stringpar p1, stringpar p2, stringpar p3) { basicrep(x); parrep(x,"1",p1.v); parrep(x,"2",p2.v); @@ -350,7 +346,7 @@ string XLAT(string x, stringpar p1, stringpar p2, stringpar p3) { postrep(x); return x; } -string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4) { +EX string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4) { basicrep(x); parrep(x,"1",p1.v); parrep(x,"2",p2.v); @@ -359,7 +355,7 @@ string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4) { postrep(x); return x; } -string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4, stringpar p5) { +EX string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4, stringpar p5) { basicrep(x); parrep(x,"1",p1.v); parrep(x,"2",p2.v); @@ -371,7 +367,7 @@ string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4, st } -string XLATN(string x) { +EX string XLATN(string x) { #if CAP_TRANS if(lang()) { const fullnoun *N = findInHashTable(x, all_nouns); @@ -381,7 +377,7 @@ string XLATN(string x) { return x; } -string XLAT1(string x) { +EX string XLAT1(string x) { #if CAP_TRANS if(lang()) { const fullnoun *N = findInHashTable(x, all_nouns); @@ -391,6 +387,6 @@ string XLAT1(string x) { return x; } -string XLATT1(stringpar p) { return XLAT1(p.v); } +EX string XLATT1(stringpar p) { return XLAT1(p.v); } } diff --git a/makeh.cpp b/makeh.cpp index 1152695f..34714666 100644 --- a/makeh.cpp +++ b/makeh.cpp @@ -45,6 +45,10 @@ void gen(string s) { in_hdr = true; continue; } + if(s == "#if CU_INIT") { + if_stack.push_back("#if 1"); + continue; + } if(s.substr(0, 3) == "#if" || s.substr(0, 4) == "# if") { if_stack.push_back(s); } diff --git a/menus.cpp b/menus.cpp index 89bc0a9c..51dd0395 100644 --- a/menus.cpp +++ b/menus.cpp @@ -7,8 +7,8 @@ #define REDDISH 0x400000 namespace hr { -ld whatever[16]; -int whateveri[16]; +EX ld whatever[16]; +EX int whateveri[16]; int PREC(ld x) { ld sh = shiftmul; @@ -16,7 +16,7 @@ int PREC(ld x) { return int(shiftmul * x); } -void showOverview() { +EX void showOverview() { cmode = sm::ZOOMABLE | sm::OVERVIEW; DEBBI(DF_GRAPH, ("show overview")); @@ -201,9 +201,9 @@ void showOverview() { // -- main menu -- -purehookset hooks_mainmenu; +EX purehookset hooks_mainmenu; -void showMainMenu() { +EX void showMainMenu() { gamescreen(2); getcstat = ' '; @@ -320,13 +320,13 @@ void showMainMenu() { // -- display modes -- -void editScale() { +EX void editScale() { dialog::editNumber(vid.scale, .001, 1000, .1, 1, XLAT("scale factor"), XLAT("Scale the displayed model.")); dialog::scaleSinh(); } -void showGraphQuickKeys() { +EX void showGraphQuickKeys() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(0); @@ -370,7 +370,7 @@ void showGraphQuickKeys() { }; } -void enable_cheat() { +EX void enable_cheat() { if(tactic::on && gold()) { addMessage(XLAT("Not available in the pure tactics mode!")); } @@ -394,7 +394,7 @@ void enable_cheat() { // -- game modes -- -void switchHardcore() { +EX void switchHardcore() { if(hardcore && !canmove) { restart_game(); hardcore = false; @@ -408,7 +408,7 @@ void switchHardcore() { if(pureHardcore()) popScreenAll(); } -void showCreative() { +EX void showCreative() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(3); dialog::init(XLAT("creative mode")); @@ -476,7 +476,7 @@ void showCreative() { dialog::display(); } -void show_chaos() { +EX void show_chaos() { gamescreen(3); dialog::init(XLAT("Chaos mode")); chaosUnlocked = chaosUnlocked || autocheat; @@ -515,7 +515,7 @@ void show_chaos() { dialog::display(); } -void showChangeMode() { +EX void showChangeMode() { gamescreen(3); dialog::init(XLAT("special modes")); // gameplay modes @@ -624,9 +624,9 @@ void showChangeMode() { }; } -bool showstartmenu; +EX bool showstartmenu; -bool showHalloween() { +EX bool showHalloween() { time_t t = time(NULL); struct tm tm = *localtime(&t); int month = tm.tm_mon + 1; @@ -640,7 +640,7 @@ int daily_mode; purehookset hooks_startmenu; -void showStartMenu() { +EX void showStartMenu() { if(!daily_mode) { daily_mode = hrand(10) + 1; if(showHalloween()) @@ -873,9 +873,14 @@ void showStartMenu() { // -- overview -- -hookset *hooks_o_key; +#if HDR +typedef pair named_functionality; +inline named_functionality named_dialog(string x, reaction_t dialog) { return named_functionality(x, [dialog] () { pushScreen(dialog); }); } +#endif -named_functionality get_o_key() { +EX hookset *hooks_o_key; + +EX named_functionality get_o_key() { if(hooks_o_key) for(auto& h: *hooks_o_key) { auto res = h.second(); @@ -917,7 +922,7 @@ int messagelogpos; int timeformat; int stampbase; -string gettimestamp(msginfo& m) { +EX string gettimestamp(msginfo& m) { char buf[128]; switch(timeformat) { case 0: @@ -941,7 +946,7 @@ string gettimestamp(msginfo& m) { return ""; } -void showMessageLog() { +EX void showMessageLog() { DEBBI(DF_GRAPH, ("show message log")); int lines = vid.yres / vid.fsize - 2; diff --git a/monstergen.cpp b/monstergen.cpp index 85a9a5ba..366efa14 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -6,10 +6,10 @@ namespace hr { -bool timerghost = true; -bool gen_wandering = true; +EX bool timerghost = true; +EX bool gen_wandering = true; -int buildIvy(cell *c, int children, int minleaf) { +EX int buildIvy(cell *c, int children, int minleaf) { if(c->monst) return 0; c->mondir = NODIR; c->monst = moIvyRoot; @@ -42,7 +42,7 @@ int buildIvy(cell *c, int children, int minleaf) { // the 'chasmify' functions create a simulation of the path the monster came by -void chasmify(cell *c) { +EX void chasmify(cell *c) { c->wall = waChasm; c->item = itNone; int q = 0; cell *c2[10]; @@ -54,7 +54,7 @@ void chasmify(cell *c) { } } -void chasmifyEarth(cell *c) { +EX void chasmifyEarth(cell *c) { int q = 0; int d2[10]; for(int i=2; i<=c->type-2; i++) { @@ -79,7 +79,7 @@ void chasmifyEarth(cell *c) { earthWall(c); c->item = itNone; } -void chasmifyElemental(cell *c) { +EX void chasmifyElemental(cell *c) { int q = 0; int d2[10]; for(int i=2; i<=c->type-2; i++) { @@ -106,7 +106,7 @@ void chasmifyElemental(cell *c) { // an appropriate monster for the Crossroads -eMonster crossroadsMonster() { +EX eMonster crossroadsMonster() { static eMonster weak[9] = { moYeti, moGoblin, moRanger, moOrangeDog, moRunDog, moMonkey, moZombie, @@ -132,14 +132,14 @@ eMonster crossroadsMonster() { return mo; } -eMonster wanderingCrossroadsMonster() { +EX eMonster wanderingCrossroadsMonster() { while(true) { eMonster m = crossroadsMonster(); if(!isIvy(m) && m != moTentacle) return m; } } -int palaceHP() { +EX int palaceHP() { if(tactic::on && isCrossroads(firstland)) return 4; if(items[itPalace] < 3) // 1+2 @@ -155,32 +155,32 @@ int palaceHP() { else return 7; } -int hardness_empty() { +EX int hardness_empty() { return yendor::hardness() * (yendor::hardness() * 3/5 - 2); } -bool redtrolls(cell *c) { +EX bool redtrolls(cell *c) { return false; /* int cd = getCdata(c, 2); cd &= 63; return cd < 32; */ } -eMonster pickTroll(cell *c) { +EX eMonster pickTroll(cell *c) { if(redtrolls(c)) return pick(moTroll,moDarkTroll,moRedTroll); else return pick(moForestTroll, moStormTroll, moFjordTroll); } -void dieTroll(cell *c, eMonster m) { +EX void dieTroll(cell *c, eMonster m) { if(m == moTroll) c->wall = waDeadTroll; else if(m == moDarkTroll) c->wall = waDeadfloor2; else if(m == moRedTroll) c->wall = waRed1; else c->wall = waDeadTroll2, c->wparam = m; } -int reptilemax() { +EX int reptilemax() { int i = items[itDodeca] + yendor::hardness(); if(i >= 245) return 5; int r = (250 - i); @@ -225,7 +225,7 @@ void wanderingZebra(cell *start) { } } -int getGhostTimer() { +EX int getGhostTimer() { return shmup::on ? (shmup::curtime - lastexplore) / 350 : turncount - lastexplore; } @@ -261,7 +261,7 @@ bool canReachPlayer(cell *cf, eMonster m) { return false; } -bool haveOrbPower() { +EX bool haveOrbPower() { for(int i=0; ic7; if(c->monst == moKrakenH || c->monst == moKrakenT) return true; @@ -283,7 +283,7 @@ bool haveKraken() { return false; } -eItem wanderingTreasure(cell *c) { +EX eItem wanderingTreasure(cell *c) { eLand l = c->land; #if CAP_DAILY if(daily::on && daily::prevent_spawn_treasure_on(c)) return itNone; @@ -305,7 +305,7 @@ eItem wanderingTreasure(cell *c) { return treasureType(l); } -void wandering() { +EX void wandering() { if(bounded && specialland == laMinefield) { kills[moBomberbird] = 0; kills[moTameBomberbird] = 0; @@ -728,7 +728,7 @@ void wandering() { } } -void generateSnake(cell *c, int i, int snakecolor) { +EX void generateSnake(cell *c, int i, int snakecolor) { c->monst = moHexSnake; c->hitpoints = snakecolor; int cpair = (1<move(i))); diff --git a/multigame.cpp b/multigame.cpp index 1955f2b8..cc0610aa 100644 --- a/multigame.cpp +++ b/multigame.cpp @@ -50,37 +50,38 @@ void gamedata::restoregame() { gamedata_all(*this); } -hookset *hooks_gamedata; +EX hookset *hooks_gamedata; -namespace gamestack { +EX namespace gamestack { vector gd; - bool pushed() { return isize(gd); } + EX bool pushed() { return isize(gd); } - void push() { + EX void push() { gd.emplace_back(); gd.back().storegame(); } - void pop() { + EX void pop() { if(!pushed()) return; if(game_active) stop_game(); gd.back().restoregame(); gd.pop_back(); } - }; +EX } -namespace dual { - int state; - - int currently_loaded; - int main_side; - bool affect_both; +EX namespace dual { + // 0 = dualmode off, 1 = in dualmode (no game chosen), 2 = in dualmode (working on one of subgames) + EX int state; + + EX int currently_loaded; + EX int main_side; + EX bool affect_both; gamedata dgd[2]; - transmatrix player_orientation[2]; + EX transmatrix player_orientation[2]; hyperpoint which_dir; @@ -101,7 +102,7 @@ namespace dual { return d; } - transmatrix get_orientation() { + EX transmatrix get_orientation() { if(WDIM == 2) return gpushxto0(tC0(cwtV)) * cwtV; else if(cwt.at) @@ -110,7 +111,7 @@ namespace dual { return Id; } - void switch_to(int k) { + EX void switch_to(int k) { if(k != currently_loaded) { // gamedata has shmup::on because tutorial needs changing it, but dual should keep it fixed dynamicval smon(shmup::on); @@ -121,7 +122,7 @@ namespace dual { } } - bool movepc(int d, int subdir, bool checkonly) { + EX bool movepc(int d, int subdir, bool checkonly) { dynamicval dm(dual::state, 2); int cg = currently_loaded; @@ -202,13 +203,13 @@ namespace dual { return false; } - void in_subscreen(reaction_t what) { + EX void in_subscreen(reaction_t what) { dynamicval xmax(current_display->xmax, 0.5 * (currently_loaded+1)); dynamicval xmin(current_display->xmin, 0.5 * (currently_loaded)); what(); } - bool split(reaction_t what) { + EX bool split(reaction_t what) { if(state != 1) return false; state = 2; @@ -221,7 +222,7 @@ namespace dual { return true; } - void enable() { + EX void enable() { if(dual::state) return; stop_game(); eGeometry b = geometry; @@ -259,7 +260,7 @@ namespace dual { state = 1; } - void disable() { + EX void disable() { if(!dual::state) return; stop_game(); state = 0; @@ -293,11 +294,11 @@ namespace dual { vector landsides; - bool check_side(eLand l) { + EX bool check_side(eLand l) { return landsides[l] == currently_loaded || landsides[l] == 2; } - void assign_landsides() { + EX void assign_landsides() { landsides.resize(landtypes); int which_hyperbolic = -1; if(ginf[dgd[0].geo].cclass == gcHyperbolic && ginf[dgd[1].geo].cclass != gcHyperbolic) @@ -360,7 +361,7 @@ namespace dual { } - void add_choice() { + EX void add_choice() { if(!state) return; dialog::addSelItem(XLAT("subgame affected"), XLAT(affect_both ? "both" : main_side == 0 ? "left" : "right"), '`'); @@ -373,12 +374,12 @@ namespace dual { }); } - void split_or_do(reaction_t what) { + EX void split_or_do(reaction_t what) { if(split(what)) return; else what(); } - bool may_split(reaction_t what) { + EX bool may_split(reaction_t what) { if(state == 1 && affect_both) { split(what); return true; @@ -386,7 +387,7 @@ namespace dual { return false; } - void may_split_or_do(reaction_t what) { + EX void may_split_or_do(reaction_t what) { if(state == 1 && affect_both) { split(what); } @@ -394,4 +395,9 @@ namespace dual { } } + #if HDR + inline reaction_t mayboth(reaction_t what) { return [=] { may_split_or_do(what); }; } + #endif + + } diff --git a/orbgen.cpp b/orbgen.cpp index b7d435a2..68c1c87f 100644 --- a/orbgen.cpp +++ b/orbgen.cpp @@ -130,7 +130,7 @@ const vector orbinfos = { {orbgenflags::S_NATIVE, laWhirlpool, 0, 2000, itOrbWater}, // needs to be last }; -eItem nativeOrbType(eLand l) { +EX eItem nativeOrbType(eLand l) { if(isElemental(l)) l = laElementalWall; if(inv::on && (l == laMirror || l == laMirrorOld || isCrossroads(l))) return itOrbMirror; @@ -352,7 +352,7 @@ eOrbLandRelation getOLR(eItem it, eLand l) { return olrPrize25; } -int orbsUnlocked() { +EX int orbsUnlocked() { int i = 0; for(int t=0; t= R10) @@ -360,20 +360,20 @@ int orbsUnlocked() { return i; } -ld orbprizefun(int tr) { +EX ld orbprizefun(int tr) { if(tactic::on) return 1; if(tr < 10) return 0; return .6 + .4 * log(tr/25.) / log(2); } -ld orbcrossfun(int tr) { +EX ld orbcrossfun(int tr) { if(tactic::on) return 1; if(tr < 10) return 0; if(tr > 25) return 1; return (tr*2 + 50) / 100.; } -bool buildPrizeMirror(cell *c, int freq) { +EX bool buildPrizeMirror(cell *c, int freq) { if(inv::on) return false; if(items[itShard] < 25) return false; if(freq && hrand(freq * 100 / orbprizefun(items[itShard])) >= 100) @@ -381,7 +381,7 @@ bool buildPrizeMirror(cell *c, int freq) { return mirror::build(c); } -eLand getPrizeLand(cell *c = cwt.at) { +EX eLand getPrizeLand(cell *c IS(cwt.at)) { eLand l = c->land; if(isElemental(l)) l = laElementalWall; if(l == laPalace && princess::dist(c) < OUT_OF_PRISON) @@ -389,7 +389,7 @@ eLand getPrizeLand(cell *c = cwt.at) { return l; } -void placePrizeOrb(cell *c) { +EX void placePrizeOrb(cell *c) { if(peace::on) return; if(daily::on) return; @@ -439,11 +439,11 @@ void placePrizeOrb(cell *c) { } // 10 not in chaos, less in chaos -int treasureForLocal() { +EX int treasureForLocal() { return (chaosmode ? 1+hrand(10) : 10); } -bool extra_safety_for_memory(cell *c) { +EX bool extra_safety_for_memory(cell *c) { if(hyperbolic && (archimedean || S3 > 3) && !quotient && !tactic::on && in_full_game()) { if(hrand(1000) < 1) { c->item = itOrbSafety; @@ -453,7 +453,7 @@ bool extra_safety_for_memory(cell *c) { return false; } -void placeLocalOrbs(cell *c) { +EX void placeLocalOrbs(cell *c) { eLand l = c->land; if(l == laZebra && c->wall == waTrapdoor) return; if(isGravityLand(l) && l != laWestWall && cellEdgeUnstable(c)) return; @@ -495,7 +495,7 @@ void placeLocalOrbs(cell *c) { } } -void placeLocalSpecial(cell *c, int outof, int loc=1, int priz=1) { +EX void placeLocalSpecial(cell *c, int outof, int loc IS(1), int priz IS(1)) { if(safety || daily::on || extra_safety_for_memory(c) || peace::on) return; int i = hrand(outof); if(i < loc && items[treasureType(c->land)] >= treasureForLocal() && !inv::on) @@ -504,7 +504,7 @@ void placeLocalSpecial(cell *c, int outof, int loc=1, int priz=1) { placePrizeOrb(c); } -void placeCrossroadOrbs(cell *c) { +EX void placeCrossroadOrbs(cell *c) { if(peace::on) return; if(daily::on) return; for(auto& oi: orbinfos) { @@ -540,7 +540,7 @@ void placeCrossroadOrbs(cell *c) { } } -void placeOceanOrbs(cell *c) { +EX void placeOceanOrbs(cell *c) { if(peace::on) return; for(auto& oi: orbinfos) { if(!(oi.flags & orbgenflags::CROSS10)) continue; diff --git a/orbs.cpp b/orbs.cpp index e183e0b3..eb1febea 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -6,48 +6,48 @@ namespace hr { -bool markOrb(eItem it) { +EX bool markOrb(eItem it) { if(!items[it]) return false; orbused[it] = true; return true; } -bool markEmpathy(eItem it) { +EX bool markEmpathy(eItem it) { if(!items[itOrbEmpathy]) return false; if(!markOrb(it)) return false; markOrb(itOrbEmpathy); return true; } -bool markEmpathy2(eItem it) { +EX bool markEmpathy2(eItem it) { if(items[itOrbEmpathy] < 2) return false; if(!markOrb2(it)) return false; markOrb2(itOrbEmpathy); return true; } -bool markOrb2(eItem it) { +EX bool markOrb2(eItem it) { return markOrb(it); /* if(!items[it]) return false; orbused[it] = true; return items[it] > 1; */ } -int fixpower(int qty) { +EX int fixpower(int qty) { if(markOrb(itOrbEnergy)) qty = (qty+1)/2; return qty; } -void useupOrb(eItem it, int qty) { +EX void useupOrb(eItem it, int qty) { items[it] -= fixpower(qty); if(items[it] < 0) items[it] = 0; } -void drainOrb(eItem it, int target) { +EX void drainOrb(eItem it, int target) { if(items[it] > target) useupOrb(it, items[it] - target); } -void empathyMove(cell *c, cell *cto, int dir) { +EX void empathyMove(cell *c, cell *cto, int dir) { if(!items[itOrbEmpathy]) return; if(items[itOrbFire]) { @@ -67,7 +67,7 @@ void empathyMove(cell *c, cell *cto, int dir) { } } -bool reduceOrbPower(eItem it, int cap) { +EX bool reduceOrbPower(eItem it, int cap) { if(items[it] && (lastorbused[it] || (it == itOrbShield && items[it]>3) || !markOrb(itOrbTime))) { items[it] -= multi::activePlayers(); if(isHaunted(cwt.at->land)) survivalist = false; @@ -83,14 +83,14 @@ bool reduceOrbPower(eItem it, int cap) { return false; } -void reduceOrbPowerAlways(eItem it) { +EX void reduceOrbPowerAlways(eItem it) { if(items[it]) { items[it] -= multi::activePlayers(); if(items[it] < 0) items[it] = 0; } } -void reduceOrbPowers() { +EX void reduceOrbPowers() { if(haveMount()) markOrb(itOrbDomination); for(int i=0; iwall = cwt.at->wall; @@ -168,7 +168,7 @@ void flashAlchemist(cell *c) { } } -void flashCell(cell *c, eMonster killer, flagtype flags) { +EX void flashCell(cell *c, eMonster killer, flagtype flags) { eWall ow = c->wall; flashAlchemist(c); if((flags & AF_MSG) && c->monst && !isWorm(c) && c->monst != moShadow) @@ -228,7 +228,7 @@ void flashCell(cell *c, eMonster killer, flagtype flags) { activateActiv(c, false); } -void activateFlashFrom(cell *cf, eMonster who, flagtype flags) { +EX void activateFlashFrom(cell *cf, eMonster who, flagtype flags) { drawFlash(cf); playSound(cf, "storm"); for(int i=0; itype; i++) @@ -252,7 +252,7 @@ bool distanceBound(cell *c1, cell *c2, int d) { return false; } -void checkFreedom(cell *cf) { +EX void checkFreedom(cell *cf) { manual_celllister cl; cl.add(cf); for(int i=0; iwall == waBarrier || c->wall == waCamelot || c->wall == waPalace || c->wall == waPlatform || c->wall == waTempWall || c->wall == waWarpGate || c->wall == waBarrowDig || c->wall == waBarrowWall; } -bool reflectingBarrierAt(cellwalker& c, int d) { +EX bool reflectingBarrierAt(cellwalker& c, int d) { if(d >= 3) return true; if(d <= -3) return true; d = c.spin + d + MODFIXER; @@ -327,7 +327,7 @@ bool reflectingBarrierAt(cellwalker& c, int d) { // return false; } -void killAdjacentSharks(cell *c) { +EX void killAdjacentSharks(cell *c) { for(int i=0; itype; i++) { cell *c2 = c->move(i); if(!c2) continue; @@ -348,7 +348,7 @@ void killAdjacentSharks(cell *c) { } } -void castLightningBolt(cellwalker lig) { +EX void castLightningBolt(cellwalker lig) { int bnc = 0; int counter = 1000; while(true) { @@ -475,11 +475,11 @@ void castLightningBolt(cellwalker lig) { } } -void castLightningBoltFrom(cell *c) { +EX void castLightningBoltFrom(cell *c) { for(int i=0; itype; i++) castLightningBolt(cellwalker(c, i)); } -void activateLightning() { +EX void activateLightning() { int tk = tkills(); drawLightning(); addMessage(XLAT("You activate the Lightning spell!")); @@ -503,7 +503,7 @@ void activateLightning() { // roMouse/roKeyboard: // return orb type if successful, eItem(-1) if do nothing, 0 otherwise -bool haveRangedTarget() { +EX bool haveRangedTarget() { if(!haveRangedOrb()) return false; for(int i=0; imonst) return moNone; if(dest->wall == waVineHalfA || dest->wall == waVineHalfB || dest->wall == waVinePlant) return moVineSpirit; @@ -882,7 +882,7 @@ void gun_attack(cell *dest) { monstersTurn(); } -void checkStunKill(cell *dest) { +EX void checkStunKill(cell *dest) { if(isBird(dest->monst)) { moveEffect(dest, dest, moDeadBird, NOHINT); doesFall(dest); @@ -1001,10 +1001,10 @@ bool monstersnearO(orbAction a, cell *c, cell *nocount, eMonster who, cell *push else return monstersnear(c, nocount, who, pushto, comefrom); } -bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; } -bool isWeakCheck(orbAction a) { return a == roCheck || a == roMultiCheck || a == roMouse; } +EX bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; } +EX bool isWeakCheck(orbAction a) { return a == roCheck || a == roMultiCheck || a == roMouse; } -cell *blowoff_destination(cell *c, int& di) { +EX cell *blowoff_destination(cell *c, int& di) { int d = 0; for(; dtype; d++) if(c->move(d) && c->move(d)->cpdist < c->cpdist) break; if(dtype) for(int e=d; etype; e++) { @@ -1015,7 +1015,7 @@ cell *blowoff_destination(cell *c, int& di) { return NULL; } -eItem targetRangedOrb(cell *c, orbAction a) { +EX eItem targetRangedOrb(cell *c, orbAction a) { if(!haveRangedOrb()) { return itNone; @@ -1351,7 +1351,7 @@ eItem targetRangedOrb(cell *c, orbAction a) { return eItem(-1); } -int orbcharges(eItem it) { +EX int orbcharges(eItem it) { switch(it) { case itRevolver: //pickup-key return 6 - items[itRevolver]; @@ -1442,7 +1442,7 @@ int orbcharges(eItem it) { } } -bool isShmupLifeOrb(eItem it) { +EX bool isShmupLifeOrb(eItem it) { return it == itOrbLife || it == itOrbFriend || it == itOrbNature || it == itOrbEmpathy || @@ -1450,7 +1450,7 @@ bool isShmupLifeOrb(eItem it) { it == itOrbDomination || it == itOrbGravity; } -void makelava(cell *c, int i) { +EX void makelava(cell *c, int i) { if(!pseudohept(c)) return; if(isPlayerOn(c)) return; if(c->wall == waFire && c->wparam < i) diff --git a/pattern2.cpp b/pattern2.cpp index 120ed287..8d2a9d8c 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -266,7 +266,7 @@ int dir_bitrunc457(cell *c) { int val46(cell *c); -int zebra40(cell *c) { +EX int zebra40(cell *c) { if(euclid) return eupattern(c); else if(IRREGULAR) return c->master->zebraval/10; else if(a46) { diff --git a/penrose.cpp b/penrose.cpp index ba389da8..ba13a440 100644 --- a/penrose.cpp +++ b/penrose.cpp @@ -3,9 +3,13 @@ namespace hr { -namespace kite { +EX namespace kite { #if CAP_BT +#if HDR +enum pshape {pDart, pKite}; +#endif + transmatrix meuscale(ld z) { if(euclid) { transmatrix T = Id; @@ -47,9 +51,9 @@ const ld up = 1 / tan(72 * degree); const ld dart_center = (down + 2 * up) / 3; const ld kite_center = up; -pshape getshape(heptagon *h) { return pshape(h->s); } +EX pshape getshape(heptagon *h) { return pshape(h->s); } -hyperpoint get_corner(cell *c, int d, ld cf) { +EX hyperpoint get_corner(cell *c, int d, ld cf) { bool kite = getshape(c->master) == pKite; int t = kite ? 1 : -1; ld shf = kite ? kite_center : dart_center; @@ -66,7 +70,7 @@ hyperpoint get_corner(cell *c, int d, ld cf) { return C0; /* unreachable! */ } -pair>, vector>> make_walls() { +EX pair>, vector>> make_walls() { vector> kv; vector> weights; @@ -365,14 +369,14 @@ struct hrmap_kite : hrmap { }; -hrmap *new_map() { return new hrmap_kite; } +EX hrmap *new_map() { return new hrmap_kite; } hrmap_kite *kite_map() { return (hrmap_kite*) currentmap; } void con(cell *c0, int d0, cell *c1, int d1) { c0->c.connect(d0, c1, d1, false); } -void find_cell_connection(cell *c, int d) { +EX void find_cell_connection(cell *c, int d) { auto h0 = c->master; auto sh = getshape(h0); auto crule = [&] (pshape s0, int d0, pshape s1, int d1, pshape sparent, int child, int sibling, int rsibling) { diff --git a/quit.cpp b/quit.cpp index 2cb3bad3..d3f25e93 100644 --- a/quit.cpp +++ b/quit.cpp @@ -5,15 +5,15 @@ namespace hr { bool quitsaves() { return (items[itOrbSafety] && CAP_SAVE && !archimedean); } -bool needConfirmationEvenIfSaved() { +EX bool needConfirmationEvenIfSaved() { return canmove && (gold() >= 30 || tkills() >= 50) && !cheater; } -bool needConfirmation() { +EX bool needConfirmation() { return needConfirmationEvenIfSaved() && !quitsaves(); } -int getgametime() { +EX int getgametime() { return (int) (savetime + (timerstopped ? 0 : (time(NULL) - timerstart))); } @@ -289,7 +289,7 @@ eLand nextHyperstone() { return laCrossroads; } -void showMission() { +EX void showMission() { cmode = sm::DOTOUR | sm::MISSION | sm::CENTER; gamescreen(1); drawStats(); @@ -456,7 +456,7 @@ void showMission() { dialog::display(); } -void handleKeyQuit(int sym, int uni) { +EX void handleKeyQuit(int sym, int uni) { dialog::handleNavigation(sym, uni); // ignore the camera movement keys @@ -511,7 +511,7 @@ int counthints() { for(int h=0;; h++) if(hints[h].last < 0) return h; } -void showMissionScreen() { +EX void showMissionScreen() { cancel(); cancel = noaction; popScreenAll(); achievement_final(false); diff --git a/racing.cpp b/racing.cpp index 91cc99ab..22101bea 100644 --- a/racing.cpp +++ b/racing.cpp @@ -7,28 +7,28 @@ namespace hr { -namespace racing { +EX namespace racing { void set_race_configurer(); -bool guiding = false; +EX bool guiding = false; -bool on; -bool player_relative = false; -bool standard_centering = false; -bool track_ready; +EX bool on; +EX bool player_relative = false; +EX bool standard_centering = false; +EX bool track_ready; bool official_race = false; int TWIDTH; -ld race_advance = 0; +EX ld race_advance = 0; static const int LENGTH = 250; static const int DROP = 1; -int ghosts_to_show = 5; -int ghosts_to_save = 10; +EX int ghosts_to_show = 5; +EX int ghosts_to_save = 10; struct race_cellinfo { cell *c; @@ -38,24 +38,24 @@ struct race_cellinfo { }; vector rti; -vector track; +EX vector track; map rti_id; int trophy[MAXPLAYER]; -string track_code = "OFFICIAL"; +EX string track_code = "OFFICIAL"; transmatrix straight; int race_try; -void apply_seed() { +EX void apply_seed() { int s = race_try; for(char c: track_code) s = 713 * s + c; shrand(s); } -int race_start_tick, race_finish_tick[MAXPLAYER]; +EX int race_start_tick, race_finish_tick[MAXPLAYER]; typedef unsigned char uchar; @@ -289,7 +289,7 @@ void find_track(cell *start, int sign, int len) { track = build_shortest_path(start, goal); } -void generate_track() { +EX void generate_track() { TWIDTH = getDistLimit() - 1; if(TWIDTH == 1) TWIDTH = 2; @@ -682,7 +682,7 @@ void generate_track() { bool inrec = false; -ld race_angle = 90; +EX ld race_angle = 90; bool set_view() { @@ -823,7 +823,7 @@ auto hook = ; #endif -vector race_lands = { +EX vector race_lands = { laHunting, laCrossroads, laJungle, @@ -850,7 +850,7 @@ vector playercmds_race = { "", "change camera", "", "" }; -string racetimeformat(int t) { +EX string racetimeformat(int t) { string times = ""; int digits = 0; bool minus = (t < 0); @@ -1130,7 +1130,7 @@ void race_projection() { } /* }; */ -void configure_race() { +EX void configure_race() { set_race_configurer(); pushScreen(raceconfigurer); @@ -1157,7 +1157,7 @@ void uploadScore() { achievement_score(LB_RACING, tscore); } -void displayScore(eLand l) { +EX void displayScore(eLand l) { int vf = min((vid.yres-64) / 70, vid.xres/80); int x = vid.xres / 4; @@ -1179,7 +1179,7 @@ void displayScore(eLand l) { } } -void race_won() { +EX void race_won() { if(!race_finish_tick[multi::cpid]) { int result = ticks - race_start_tick; int losers = 0; @@ -1358,7 +1358,7 @@ void markers() { } } -void add_debug(cell *c) { +EX void add_debug(cell *c) { if(racing::on && racing::rti_id[c]) { auto& r = racing::get_info(c); dialog::addSelItem("from_track", its(r.from_track), 0); diff --git a/renderbuffer.cpp b/renderbuffer.cpp index 3cab0e58..2847b4af 100644 --- a/renderbuffer.cpp +++ b/renderbuffer.cpp @@ -126,7 +126,7 @@ SDL_Surface *renderbuffer::render() { } #endif -int current_rbuffer = -1; +EX int current_rbuffer = -1; void renderbuffer::enable() { #if CAP_GL diff --git a/screenshot.cpp b/screenshot.cpp index 6ea5573a..2e982b5d 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -472,7 +472,7 @@ void menu() { #endif #if CAP_ANIMATIONS -namespace anims { +EX namespace anims { enum eMovementAnimation { maNone, maTranslation, maRotation, maCircle, maParabolic, maTranslationRotation @@ -480,19 +480,19 @@ enum eMovementAnimation { eMovementAnimation ma; -ld shift_angle, movement_angle; -ld normal_angle = 90; -ld period = 10000; -int noframes = 30; -ld cycle_length = 2 * M_PI; -ld parabolic_length = 1; -ld skiprope_rotation; +EX ld shift_angle, movement_angle; +EX ld normal_angle = 90; +EX ld period = 10000; +EX int noframes = 30; +EX ld cycle_length = 2 * M_PI; +EX ld parabolic_length = 1; +EX ld skiprope_rotation; int lastticks, bak_turncount; -ld rug_rotation1, rug_rotation2, ballangle_rotation, env_ocean, env_volcano; -bool env_shmup; -ld rug_angle; +EX ld rug_rotation1, rug_rotation2, ballangle_rotation, env_ocean, env_volcano; +EX bool env_shmup; +EX ld rug_angle; heptspin rotation_center_h; cellwalker rotation_center_c; @@ -500,7 +500,7 @@ transmatrix rotation_center_View; color_t circle_display_color = 0x00FF00FF; -ld circle_radius = acosh(2.), circle_spins = 1; +EX ld circle_radius = acosh(2.), circle_spins = 1; void moved() { optimizeview(); @@ -577,7 +577,7 @@ void reflect_view() { bool clearup; -void apply() { +EX void apply() { int t = ticks - lastticks; lastticks = ticks; @@ -701,14 +701,14 @@ void apply() { calcparam(); } -void rollback() { +EX void rollback() { if(env_volcano) { turncount = bak_turncount; } } #if CAP_FILES && CAP_SHOT -string animfile = "animation-%04d.png"; +EX string animfile = "animation-%04d.png"; int min_frame = 0, max_frame = 999999; @@ -796,7 +796,7 @@ void list_animated_parameters() { ld animation_period; -void show() { +EX void show() { cmode = sm::SIDE; needs_highqual = false; animation_lcm = 1; gamescreen(0); @@ -1080,7 +1080,7 @@ auto animhook = addHook(hooks_frame, 100, display_animation) #endif ; -bool any_animation() { +EX bool any_animation() { if(conformal::on) return true; if(ma) return true; if(ballangle_rotation || rug_rotation1 || rug_rotation2) return true; @@ -1088,22 +1088,22 @@ bool any_animation() { return false; } -bool any_on() { +EX bool any_on() { return any_animation() || conformal::includeHistory; } -bool center_music() { +EX bool center_music() { return among(ma, maParabolic, maTranslation); } -} +EX } #endif -namespace startanims { +EX namespace startanims { int ticks_start = 0; -void null_animation() { +EX void null_animation() { gamescreen(2); } @@ -1240,9 +1240,9 @@ void fib_ghosts() { // - fly a ghost around center, in Gans model // - triangle edges? -reaction_t current = null_animation; +EX reaction_t current = null_animation; -void pick() { +EX void pick() { if(((gold() > 0 || tkills() > 0) && canmove) || geometry != gNormal || ISWEB || ISMOBILE || vid.always3 || pmodel || rug::rugged || vid.wallmode < 2 || vid.monmode < 2 || glhr::noshaders || !vid.usingGL) { current = null_animation; return; @@ -1257,5 +1257,5 @@ void pick() { auto sanimhook = addHook(hooks_frame, 100, []() { if(add_to_frame) add_to_frame(); }); #endif -} +EX } } diff --git a/sound.cpp b/sound.cpp index 46fe76d0..1c833f4b 100644 --- a/sound.cpp +++ b/sound.cpp @@ -7,16 +7,16 @@ const char *musicfile = ""; bool audio; string musiclicense; string musfname[landtypes]; -int musicvolume = 60, effvolume = 60; +EX int musicvolume = 60, effvolume = 60; -eLand getCurrentLandForMusic() { +EX eLand getCurrentLandForMusic() { eLand id = ((anims::center_music()) && centerover.at) ? centerover.at->land : cwt.at->land; if(isHaunted(id)) id = laHaunted; if(id == laWarpSea) id = laWarpCoast; return id; } -void playSeenSound(cell *c) { +EX void playSeenSound(cell *c) { if(!c->monst) return; bool nearme = c->cpdist <= 7; forCellEx(c2, c) if(c2->cpdist <= 7) nearme = true; @@ -73,7 +73,7 @@ eLand cid = laNone; hookset *hooks_music; -void handlemusic() { +EX void handlemusic() { DEBBI(DF_GRAPH, ("handle music")); if(audio && musicvolume) { eLand id = getCurrentLandForMusic(); @@ -117,7 +117,7 @@ void handlemusic() { hookset *hooks_resetmusic; -void resetmusic() { +EX void resetmusic() { if(audio && musicvolume) { Mix_FadeOutMusic(3000); cid = laNone; @@ -126,7 +126,7 @@ void resetmusic() { } } -bool loadMusicInfo(string dir) { +EX bool loadMusicInfo(string dir) { DEBBI(DF_INIT, ("load music info")); if(dir == "") return false; FILE *f = fopen(dir.c_str(), "rt"); @@ -164,7 +164,7 @@ bool loadMusicInfo(string dir) { return false; } -bool loadMusicInfo() { +EX bool loadMusicInfo() { return loadMusicInfo(musicfile) || loadMusicInfo(HYPERPATH "hyperrogue-music.txt") @@ -181,7 +181,7 @@ bool loadMusicInfo() { ; } -void initAudio() { +EX void initAudio() { audio = loadMusicInfo(); if(audio) { @@ -206,7 +206,7 @@ string wheresounds = HYPERPATH "sounds/"; hookset *hooks_sound; -void playSound(cell *c, const string& fname, int vol) { +EX void playSound(cell *c, const string& fname, int vol) { if(effvolume == 0) return; if(callhandlers(false, hooks_sound, fname, vol)) return; // printf("Play sound: %s\n", fname.c_str()); @@ -224,7 +224,7 @@ void playSound(cell *c, const string& fname, int vol) { } } -void reuse_music_memory() { +EX void reuse_music_memory() { for(int i=0; i