autohdr.h applied in more files

This commit is contained in:
Zeno Rogue 2019-08-09 21:00:52 +02:00
parent 64824390fe
commit c2d56fb9bc
44 changed files with 1451 additions and 2141 deletions

View File

@ -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<string> achievementsReceived;
// achievements received this game
EX vector<string> 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
}

View File

@ -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<int, int> 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<void()> 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.

View File

@ -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; t<S7; t++) if((!c->move(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

View File

@ -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<int, eModel, display_data*, int> 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<glhr::textured_vertex> 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<msginfo> msgs;
vector<msginfo> gamelog;
void flashMessages() {
EX void flashMessages() {
for(int i=0; i<isize(msgs); i++)
if(msgs[i].stamp < ticks - 1000 && !msgs[i].flashout) {
msgs[i].flashout = true;
@ -960,9 +963,9 @@ void addMessageToLog(msginfo& m, vector<msginfo>& 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<display_data> 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;

View File

@ -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; i<c->type; 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; i<c->type; 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<eLand> euland;
map<int, eLand> euland3;
map<int, eLand> 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; i<max_vec; i++) euland[i] = laNone;
if(!nonisotropic) euland[0] = euland[1] = euland[max_vec-1] = first;
@ -895,7 +893,7 @@ bool valid_wall_at(int c) {
return short(c) % 3 == 0;
}
eLand switchable(eLand nearland, eLand farland, int c) {
EX eLand switchable(eLand nearland, eLand farland, int c) {
if(chaosmode) {
if(hrand(6) == 0)
return getNewLand(nearland);
@ -926,7 +924,7 @@ eLand switchable(eLand nearland, eLand farland, int c) {
}
}
eLand getEuclidLand(int c) {
EX eLand getEuclidLand(int c) {
if(nonorientable && c < 0) c = -c;
auto& la = get_euland(c);
if(la) return la;
@ -939,7 +937,7 @@ eLand getEuclidLand(int c) {
return la = laCrossroads;
}
void setLandSol(cell *c) {
EX void setLandSol(cell *c) {
setland(c, specialland);
if(chaosmode) {
setland(c, getEuclidLand(c->master->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; i<c->type; 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<cell*> candidates;
for(cell *c: currentmap->allcells())
if(c->wall == waMineUnknown)
@ -1715,9 +1713,9 @@ void generate_mines() {
for(int i=0; i<bounded_mine_quantity; i++) candidates[i]->wall = waMineMine;
}
vector<eLand> currentlands;
EX vector<eLand> currentlands;
void pregen() {
EX void pregen() {
currentlands.clear();
if(chaosmode > 1)
for(eLand l: land_over)

View File

@ -27,7 +27,7 @@ struct blizzardcell {
map<cell*, blizzardcell> 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<cell*> arrowtraps;
void drawArrowTraps() {
EX void drawArrowTraps() {
for(cell *c: arrowtraps) {
auto r = traplimits(c);

116
cell.cpp
View File

@ -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<cell> (type);
c->type = type;
c->master = master;
@ -26,10 +24,10 @@ cell *newCell(int type, heptagon *master) {
// -- hrmap ---
hrmap *currentmap;
vector<hrmap*> allmaps;
EX hrmap *currentmap;
EX vector<hrmap*> 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<pair<eucoord, eucoord>, 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<hrmap_euclidean*> (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<hrmap*()> *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; t<c->type; t++) if(c->move(t)) {
@ -256,7 +254,7 @@ void clearcell(cell *c) {
tailored_delete(c);
}
heptagon deletion_marker;
EX heptagon deletion_marker;
template<class T> void subcell(cell *c, const T& t) {
if(GOLDBERG) {
@ -269,7 +267,7 @@ template<class T> 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<heptagon*> 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; i<t; i++) {
cell *c2 = c->move(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; i<at->type; 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; u<S3; u++) mi = min(mi, dx[u]);
for(int u=0; u<S3; u++)
@ -389,7 +387,7 @@ int compdist(int dx[]) {
return mi;
}
int celldist(cell *c) {
EX int celldist(cell *c) {
if(fulltorus && WDIM == 2)
return torusmap()->dists[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; i<cfrom->type; 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; i<RANDITER+1; i++)
rpm_memoize[a][b][i] = 2;
}
bool randpatternMajority(cell *c, int ival, int iterations) {
EX bool randpatternMajority(cell *c, int ival, int iterations) {
int rval = 0;
if(ival == 0) rval = randompattern[laCaves];
if(ival == 1) rval = randompattern[laLivefjord];
@ -597,7 +595,7 @@ bool randpatternMajority(cell *c, int ival, int iterations) {
cdata orig_cdata;
bool geometry_supports_cdata() {
EX bool geometry_supports_cdata() {
return among(geometry, gEuclid, gEuclidSquare, gNormal, gOctagon, g45, g46, g47, gBinaryTiling) || (archimedean && !sphere);
}
@ -618,7 +616,7 @@ void setHeptagonRval(heptagon *h) {
}
}
bool dmeq(int a, int b) { return (a&3) == (b&3); }
EX bool dmeq(int a, int b) { return (a&3) == (b&3); }
/* kept for compatibility: Racing etc. */
cdata *getHeptagonCdata_legacy(heptagon *h) {
@ -805,19 +803,19 @@ int ld_to_int(ld x) {
return int(x + 1000000.5) - 1000000;
}
int pseudocoords(cell *c) {
EX int pseudocoords(cell *c) {
transmatrix T = arcm::archimedean_gmatrix[c->master].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<eGeometry> g(geometry, gNormal);
dynamicval<hrmap*> 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<cell*> 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<cell*> 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<cell*> build_shortest_path(cell *c1, cell *c2) {
EX vector<cell*> 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<cell*> build_shortest_path(cell *c1, cell *c2) {
return p;
}
void clearCellMemory() {
EX void clearCellMemory() {
for(int i=0; i<isize(allmaps); i++)
if(allmaps[i])
delete allmaps[i];

View File

@ -250,6 +250,7 @@ extern itemtype iinf[ittypes];
extern const landtype linf[landtypes];
extern color_t floorcolors[landtypes];
extern walltype winf[walltypes];
enum cpatterntype {
cpFootball, cpThree, cpChess, cpSingle, cpSingleSym, cpOddEven, cpLarge, cpZebra, cpUnknown

View File

@ -36,7 +36,7 @@ eMonster readMonster(const string& ss) {
}
}
void initializeCLI() {
EX void initializeCLI() {
printf("HyperRogue by Zeno Rogue <zeno@attnam.com>, version " VER "\n");
#if !NOLICENSE
@ -277,9 +277,9 @@ int arg::readCommon() {
return 0;
}
purehookset hooks_config;
EX purehookset hooks_config;
hookset<int()> *hooks_args;
EX hookset<int()> *hooks_args;
namespace arg {
int curphase;

View File

@ -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<ld, gGUARD> sightranges;
EX array<ld, gGUARD> 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<isize(ct); i++)
addsaver(ct[i], "color:" + name + ":" + its(i));
}
void initConfig() {
EX void initConfig() {
// basic config
addsaver(vid.flashtime, "flashtime", 8);
@ -480,7 +480,7 @@ void initConfig() {
#endif
}
bool inSpecialMode() {
EX bool inSpecialMode() {
return chaosmode || !BITRUNCATED || peace::on ||
#if CAP_TOUR
tour::on ||
@ -491,7 +491,7 @@ bool inSpecialMode() {
vid.wallmode != DEFAULT_WALLMODE;
}
bool have_current_settings() {
EX bool have_current_settings() {
int modecount = 0;
if(inv::on) modecount++;
if(shmup::on) modecount += 10;
@ -512,7 +512,7 @@ bool have_current_settings() {
return false;
}
bool have_current_graph_settings() {
EX bool have_current_graph_settings() {
if(vid.xposition || vid.yposition || vid.alpha != 1 || vid.scale != 1)
return true;
if(pmodel != mdDisk || vid.monmode != DEFAULT_MONMODE || vid.wallmode != DEFAULT_WALLMODE)
@ -523,7 +523,7 @@ bool have_current_graph_settings() {
return false;
}
void reset_graph_settings() {
EX void reset_graph_settings() {
pmodel = mdDisk; vid.alpha = 1; vid.scale = 1;
vid.xposition = vid.yposition = 0;
#if CAP_RUG
@ -534,7 +534,7 @@ void reset_graph_settings() {
vid.wallmode = DEFAULT_WALLMODE;
}
void resetModes(char leave) {
EX void resetModes(char leave) {
while(game_active || gamestack::pushed()) {
if(game_active) stop_game();
if(gamestack::pushed()) gamestack::pop();
@ -565,7 +565,7 @@ void resetModes(char leave) {
}
#if CAP_CONFIG
void resetConfig() {
EX void resetConfig() {
dynamicval<int> rx(vid.xres, 0);
dynamicval<int> ry(vid.yres, 0);
dynamicval<int> 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<string, shared_ptr<supersaver> > allconfigs;
void parseline(const string& str) {
EX void parseline(const string& str) {
if(str[0] == '#') return;
for(int i=0; i<isize(str); i++) if(str[i] == '=') {
string cname = str.substr(0, i);
@ -632,7 +632,7 @@ void parseline(const string& str) {
printf("Warning: config line without equality sign: %s\n", str.c_str());
}
void loadNewConfig(FILE *f) {
EX void loadNewConfig(FILE *f) {
for(auto& c: savers) allconfigs[c->name] = c;
string rd;
while(true) {
@ -647,7 +647,7 @@ void loadNewConfig(FILE *f) {
allconfigs.clear();
}
void loadConfig() {
EX void loadConfig() {
DEBB(DF_INIT, ("load config"));
vid.xres = 9999; vid.yres = 9999; vid.framelimit = 300;
@ -675,7 +675,7 @@ void loadConfig() {
}
#endif
void add_cells_drawn(char c = 'C') {
EX void add_cells_drawn(char c IS('C')) {
dialog::addSelItem(XLAT("cells drawn"), (noclipped ? its(cells_drawn) + " (" + its(noclipped) + ")" : its(cells_drawn)) + " / " + its(vid.cells_drawn_limit), c);
dialog::add_action([] () {
popScreen();
@ -705,7 +705,7 @@ string solhelp() {
);
}
void edit_sightrange() {
EX void edit_sightrange() {
if(vid.use_smart_range) {
ld& det = WDIM == 2 ? vid.smart_range_detail : vid.smart_range_detail_3;
dialog::editNumber(det, 1, 50, 1, WDIM == 2 ? 8 : 30, XLAT("minimum visible cell in pixels"), "");
@ -799,7 +799,7 @@ void edit_sightrange() {
};
}
void menuitem_sightrange(char c) {
EX void menuitem_sightrange(char c) {
if(vid.use_smart_range)
dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(WDIM == 3 ? vid.smart_range_detail_3 : vid.smart_range_detail), c);
else if(pmodel == mdGeodesic && sol)
@ -811,7 +811,7 @@ void menuitem_sightrange(char c) {
dialog::add_action(edit_sightrange);
}
void showGraphConfig() {
EX void showGraphConfig() {
cmode = vid.xres > 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")) {

View File

@ -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 <void(int sym, int uni)> keyhandler = [] (int sym, int uni) {};
function <bool(SDL_Event &ev)> 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<numsticks; i++) {
SDL_JoystickClose(sticks[i]), sticks[i] = NULL;
@ -205,7 +207,7 @@ void closeJoysticks() {
numsticks = 0;
}
void checkjoy() {
EX void checkjoy() {
DEBB(DF_GRAPH, ("check joy"));
if(!DEFAULTCONTROL) return;
ld joyvalue1 = sqr(vid.joyvalue);
@ -230,7 +232,7 @@ void checkjoy() {
joydir = vectodir(hpxy(jx, jy));
}
void checkpanjoy(double t) {
EX void checkpanjoy(double t) {
if(shmup::on) return;
if(vid.joypanspeed < 1e-7) return;
@ -249,7 +251,7 @@ void checkpanjoy(double t) {
bool quitmainloop = false;
bool doexiton(int sym, int uni) {
EX bool doexiton(int sym, int uni) {
if(sym == SDLK_ESCAPE) return true;
if(sym == SDLK_F10) return true;
if(sym == PSEUDOKEY_RELEASE) return false;
@ -269,9 +271,9 @@ bool didsomething;
typedef SDL_Event eventtype;
bool smooth_scrolling = false;
EX bool smooth_scrolling = false;
void handlePanning(int sym, int uni) {
EX void handlePanning(int sym, int uni) {
if(mousepan && dual::split([=] { handlePanning(sym, uni); })) return;
if(DIM == 3) {
if(sym == PSEUDOKEY_WHEELUP) View = cpush(2, -0.05*shiftmul) * View, didsomething = true, playermoved = false;
@ -369,9 +371,9 @@ bool handleTune(int sym, int uni) {
}
#endif
purehookset hooks_fixticks;
EX purehookset hooks_fixticks;
void handleKeyNormal(int sym, int uni) {
EX void handleKeyNormal(int sym, int uni) {
if(cheater && sym < 256 && sym > 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 }
}

View File

@ -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<item> items;
EX vector<item> items;
item& lastItem() { return items[items.size() - 1]; }
EX item& lastItem() { return items[items.size() - 1]; }
map<int, reaction_t> key_actions;
EX map<int, reaction_t> 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<isize(items); i++)
if(isitem(items[i]))
@ -534,13 +582,13 @@ namespace dialog {
0x408040FF, 0xFFD500FF
}, lch;
color_t *palette;
EX color_t *palette;
int colorp = 0;
color_t *colorPointer;
void handleKeyColor(int sym, int uni) {
EX void handleKeyColor(int sym, int uni) {
unsigned& color = *colorPointer;
int shift = colorAlpha ? 0 : 8;
@ -583,9 +631,9 @@ namespace dialog {
}
}
bool colorAlpha;
EX bool colorAlpha;
void drawColorDialog() {
EX void drawColorDialog() {
cmode = sm::NUMBER | dialogflags;
if(cmode & sm::SIDE) gamescreen(0);
@ -646,7 +694,7 @@ namespace dialog {
keyhandler = handleKeyColor;
}
void openColorDialog(unsigned int& col, unsigned int *pal) {
EX void openColorDialog(unsigned int& col, unsigned int *pal IS(palette)) {
colorPointer = &col; palette = pal;
colorAlpha = true;
dialogflags = 0;
@ -655,9 +703,9 @@ namespace dialog {
extra_options = reaction_t();
}
numberEditor ne;
EX numberEditor ne;
bool editingDetail() {
EX bool editingDetail() {
return ne.editwhat == &vid.highdetail || ne.editwhat == &vid.middetail;
}
@ -666,17 +714,17 @@ namespace dialog {
else return int(x-.5);
}
string disp(ld x) {
EX string disp(ld x) {
if(dialogflags & sm::HEXEDIT) return "0x" + itsh(x);
else if(ne.intval) return its(ldtoint(x));
else return fts(x); }
reaction_t reaction;
reaction_t reaction_final;
EX reaction_t reaction;
EX reaction_t reaction_final;
reaction_t extra_options;
EX reaction_t extra_options;
void apply_slider() {
EX void apply_slider() {
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
if(reaction) reaction();
if(ne.intval) *ne.editwhat = *ne.intval;
@ -686,12 +734,12 @@ namespace dialog {
#endif
}
void use_hexeditor() {
EX void use_hexeditor() {
dialogflags |= sm::HEXEDIT;
ne.s = disp(*ne.editwhat);
}
void apply_edit() {
EX void apply_edit() {
exp_parser ep;
ep.s = ne.s;
ld x = real(ep.parse());
@ -705,7 +753,7 @@ namespace dialog {
if(reaction) reaction();
}
void bound_low(ld val) {
EX void bound_low(ld val) {
auto r = reaction;
reaction = [r, val] () {
if(*ne.editwhat < val) {
@ -716,7 +764,7 @@ namespace dialog {
};
}
void bound_up(ld val) {
EX void bound_up(ld val) {
auto r = reaction;
reaction = [r, val] () {
if(*ne.editwhat > 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<isize(s); i++) {
@ -1067,7 +1115,7 @@ namespace dialog {
return t.find(infix) != string::npos;
}
bool editInfix(int uni) {
EX bool editInfix(int uni) {
if(uni >= '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<pair<string, color_t> > v;
EX vector<pair<string, color_t> > 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<string(int, int)> checker) {
EX bool handle_edit_string(int sym, int uni, function<string(int, int)> 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<class T> 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
};
}

View File

@ -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<unique_ptr<drawqueueitem>> ptds;
EX vector<unique_ptr<drawqueueitem>> ptds;
#if CAP_GL
color_t text_color;
@ -42,7 +70,7 @@ vector<glvertex> 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<glvertex> glcoords;
EX vector<glvertex> glcoords;
#endif
@ -142,7 +170,7 @@ bool knowgood;
hyperpoint goodpoint;
vector<pair<int, hyperpoint>> 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<glvertex> 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<hyperpoint>& t, color_t fillcol, color_t linecol, int lev) {
EX void prettypoly(const vector<hyperpoint>& t, color_t fillcol, color_t linecol, int lev) {
prettylinepoints.clear();
prettypoint(t[0]);
for(int i=0; i<isize(t); i++)
@ -1168,7 +1196,7 @@ vector<glvertex> 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; i<isize(ptds);)
if(i && ptds[i]->prio < 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<PMAX; a++) qp[a] = 0;
@ -1303,18 +1331,18 @@ void sort_drawqueue() {
swap(ptds, ptds2);
}
void reverse_priority(PPR p) {
EX void reverse_priority(PPR p) {
reverse(ptds.begin()+qp0[int(p)], ptds.begin()+qp[int(p)]);
}
void reverse_side_priorities() {
EX void reverse_side_priorities() {
for(PPR p: {PPR::REDWALLs, PPR::REDWALLs2, PPR::REDWALLs3, PPR::WALL3s,
PPR::LAKEWALL, PPR::INLAKEWALL, PPR::BELOWBOTTOM})
reverse_priority(p);
}
// on the sphere, parts on the back are drawn first
void draw_backside() {
EX void draw_backside() {
if(pmodel == mdHyperboloid && hyperbolic) {
dynamicval<eModel> 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<class T, class... U> 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<dqi_poly> (prio);
@ -1540,7 +1568,7 @@ void addfloats(vector<GLfloat>& v, hyperpoint h) {
for(int i=0; i<3; i++) v.push_back(h[i]);
}
dqi_poly& queuetable(const transmatrix& V, const vector<glvertex>& f, int cnt, color_t linecol, color_t fillcol, PPR prio) {
EX dqi_poly& queuetable(const transmatrix& V, const vector<glvertex>& f, int cnt, color_t linecol, color_t fillcol, PPR prio) {
auto& ptd = queuea<dqi_poly> (prio);
@ -1559,7 +1587,7 @@ dqi_poly& queuetable(const transmatrix& V, const vector<glvertex>& 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<dqi_action> (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<dqi_line> (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<dqi_string> (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<dqi_string> (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<dqi_circle>(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

View File

@ -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<int, int> vec_to_pair(int vec) {
EX pair<int, int> 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<int, int> cell_to_pair(cell *c) {
EX pair<int, int> 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];
}

View File

@ -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;

599
game.cpp

File diff suppressed because it is too large Load Diff

View File

@ -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<string, geometry_information> cgis;

View File

@ -19,7 +19,7 @@ void fixelliptic(hyperpoint& h) {
for(int i=0; i<MDIM; i++) h[i] = -h[i];
}
transmatrix master_relative(cell *c, bool get_inverse) {
EX transmatrix master_relative(cell *c, bool get_inverse IS(false)) {
if(0) ;
#if CAP_IRR
else if(IRREGULAR) {
@ -52,11 +52,11 @@ transmatrix master_relative(cell *c, bool get_inverse) {
return pispin * Id;
}
transmatrix calc_relative_matrix(cell *c2, cell *c1, int direction_hint) {
EX transmatrix calc_relative_matrix(cell *c2, cell *c1, int direction_hint) {
return calc_relative_matrix(c2, c1, ddspin(c1, direction_hint) * xpush0(1e-2));
}
transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) {
EX transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) {
return currentmap->relative_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);

138
graph.cpp
View File

@ -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<bool(int sym, int uni)> *hooks_handleKey;
hookset<bool(cell *c, const transmatrix& V)> *hooks_drawcell;
purehookset hooks_frame, hooks_markers;
EX hookset<bool(int sym, int uni)> *hooks_handleKey;
EX hookset<bool(cell *c, const transmatrix& V)> *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<cell*, fallanim> 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<array<int,4>,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<pair<int, int> > auraspecials;
int auramemo;
void clearaura() {
EX void clearaura() {
if(!haveaura()) return;
for(int a=0; a<AURA; a++) for(int b=0; b<4; b++)
aurac[a][b] = 0;
@ -3858,7 +3858,7 @@ bool noAdjacentChasms(cell *c) {
}
// does the current geometry allow nice duals
bool has_nice_dual() {
EX bool has_nice_dual() {
#if CAP_IRR
if(IRREGULAR) return irr::bitruncations_performed > 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<hyperpoint> 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<flashdata> 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<qty; i++)
drawParticle(c, firegradient(i / (qty-1.)), maxspeed);
@ -6771,7 +6771,7 @@ void fallingMonsterAnimation(cell *c, eMonster m, int id) {
}
#if CAP_QUEUE
void queuecircleat(cell *c, double rad, color_t col) {
EX void queuecircleat(cell *c, double rad, color_t col) {
if(!c) return;
if(!gmatrix.count(c)) return;
if(WDIM == 3) {
@ -7221,7 +7221,7 @@ void precise_mouseover() {
mouseover = omouseover;
}
void drawthemap() {
EX void drawthemap() {
check_cgi();
cgi.require_shapes();
@ -7389,7 +7389,7 @@ void drawthemap() {
profile_stop(0);
}
void drawmovestar(double dx, double dy) {
EX void drawmovestar(double dx, double dy) {
DEBBI(DF_GRAPH, ("draw movestar"));
if(viewdists) return;
@ -7449,7 +7449,7 @@ bool dronemode;
purehookset hooks_calcparam;
void calcparam() {
EX void calcparam() {
DEBBI(DF_GRAPH, ("calc param"));
auto cd = current_display;
@ -7509,7 +7509,7 @@ function<void()> 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<void()> > 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<ANIMLAYERS; i++) animations[i].clear();
flashes.clear();
fallanims.clear();
@ -7841,7 +7843,7 @@ int revhint(cell *c, int hint) {
else return hint;
}
bool compute_relamatrix(cell *src, cell *tgt, int direction_hint, transmatrix& T) {
EX bool compute_relamatrix(cell *src, cell *tgt, int direction_hint, transmatrix& T) {
if(confusingGeometry()) {
T = calc_relative_matrix(src, tgt, revhint(src, direction_hint));
}
@ -7855,7 +7857,7 @@ bool compute_relamatrix(cell *src, cell *tgt, int direction_hint, transmatrix& T
}
void animateMovement(cell *src, cell *tgt, int layer, int direction_hint) {
EX void animateMovement(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;
@ -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<pair<cell*, animation> > 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<isize(animstack); i++)
animations[layer][animstack[i].first] = animstack[i].second;
animstack.clear();
}
void animateReplacement(cell *a, cell *b, int layer, int direction_hinta, int direction_hintb) {
EX void animateReplacement(cell *a, cell *b, int layer, int direction_hinta, int direction_hintb) {
if(vid.mspeed >= 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);

View File

@ -3,11 +3,11 @@
namespace hr {
string help;
EX string help;
function<void()> help_delegate;
EX function<void()> help_delegate;
vector<help_extension> help_extensions;
EX vector<help_extension> help_extensions;
vector<string> extra_keys = {
"1 = orthogonal/Gans model",
@ -726,9 +726,9 @@ void appendHelp(string s) {
unsigned char lastval;
int windtotal;
hookset<void(cell*)> *hooks_mouseover;
EX hookset<void(cell*)> *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<bool()> *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;

22
hud.cpp
View File

@ -3,18 +3,18 @@
namespace hr {
vector<radarpoint> radarpoints;
vector<radarline> radarlines;
EX vector<radarpoint> radarpoints;
EX vector<radarline> 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<bool()> *hooks_prestats;
EX hookset<bool()> *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)

917
hyper.h

File diff suppressed because it is too large Load Diff

View File

@ -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<GDIM)?1:-1; }
EX int sig(int z) { return (sphere || sol || z<GDIM)?1:-1; }
int curvature() {
EX int curvature() {
switch(cgclass) {
case gcEuclid: return 0;
case gcHyperbolic: return -1;
@ -49,7 +49,7 @@ int curvature() {
}
}
ld sin_auto(ld x) {
EX ld sin_auto(ld x) {
switch(cgclass) {
case gcEuclid: return x;
case gcHyperbolic: return sinh(x);
@ -58,7 +58,7 @@ ld sin_auto(ld x) {
}
}
ld asin_auto(ld x) {
EX ld asin_auto(ld x) {
switch(cgclass) {
case gcEuclid: return x;
case gcHyperbolic: return asinh(x);
@ -67,7 +67,7 @@ ld asin_auto(ld x) {
}
}
ld acos_auto(ld x) {
EX ld acos_auto(ld x) {
switch(cgclass) {
case gcHyperbolic: return acosh(x);
case gcSphere: return acos(x);
@ -75,7 +75,7 @@ ld acos_auto(ld x) {
}
}
ld volume_auto(ld r) {
EX ld volume_auto(ld r) {
switch(cgclass) {
case gcEuclid: return 4 * r * r * r / 3 * M_PI;
case gcHyperbolic: return M_PI * (sinh(2*r) - 2 * r);
@ -84,7 +84,7 @@ ld volume_auto(ld r) {
}
}
ld asin_auto_clamp(ld x) {
EX ld asin_auto_clamp(ld x) {
switch(cgclass) {
case gcEuclid: return x;
case gcHyperbolic: return asinh(x);
@ -93,7 +93,7 @@ ld asin_auto_clamp(ld x) {
}
}
ld cos_auto(ld x) {
EX ld cos_auto(ld x) {
switch(cgclass) {
case gcEuclid: return 1;
case gcHyperbolic: return cosh(x);
@ -102,7 +102,7 @@ ld cos_auto(ld x) {
}
}
ld tan_auto(ld x) {
EX ld tan_auto(ld x) {
switch(cgclass) {
case gcEuclid: return x;
case gcHyperbolic: return tanh(x);
@ -111,7 +111,7 @@ ld tan_auto(ld x) {
}
}
ld atan_auto(ld x) {
EX ld atan_auto(ld x) {
switch(cgclass) {
case gcEuclid: return x;
case gcHyperbolic: return atanh(x);
@ -120,7 +120,7 @@ ld atan_auto(ld x) {
}
}
ld atan2_auto(ld y, ld x) {
EX ld atan2_auto(ld y, ld x) {
switch(cgclass) {
case gcEuclid: return y/x;
case gcHyperbolic: return atanh(y/x);
@ -130,7 +130,7 @@ ld atan2_auto(ld y, ld x) {
}
// cosine rule -- edge opposite alpha
ld edge_of_triangle_with_angles(ld alpha, ld beta, ld gamma) {
EX ld edge_of_triangle_with_angles(ld alpha, ld beta, ld gamma) {
return acos_auto((cos(alpha) + cos(beta) * cos(gamma)) / (sin(beta) * sin(gamma)));
}
@ -159,17 +159,17 @@ const hyperpoint Cx13 = hyperpoint(1,0,0,1.41421356237);
#define Cx1 (GDIM==2?Cx12:Cx13)
EX bool zero_d(int d, hyperpoint h) {
for(int i=0; i<d; i++) if(h[i]) return false;
return true;
}
// this function returns approximate square of distance between two points
// (in the spherical analogy, this would be the distance in the 3D space,
// through the interior, not on the surface)
// also used to verify whether a point h1 is on the hyperbolic plane by using Hypc for h2
bool zero_d(int d, hyperpoint h) {
for(int i=0; i<d; i++) if(h[i]) return false;
return true;
}
ld intval(const hyperpoint &h1, const hyperpoint &h2) {
EX ld intval(const hyperpoint &h1, const hyperpoint &h2) {
ld res = 0;
for(int i=0; i<MDIM; i++) res += squar(h1[i] - h2[i]) * sig(i);
if(elliptic) {
@ -180,33 +180,33 @@ ld intval(const hyperpoint &h1, const hyperpoint &h2) {
return res;
}
ld sqhypot_d(int d, const hyperpoint& h) {
EX ld sqhypot_d(int d, const hyperpoint& h) {
ld sum = 0;
for(int i=0; i<d; i++) sum += h[i]*h[i];
return sum;
}
ld hypot_d(int d, const hyperpoint& h) {
EX ld hypot_d(int d, const hyperpoint& h) {
return sqrt(sqhypot_d(d, h));
}
ld sqdhypot_d(int d, const hyperpoint& a, const hyperpoint& b) {
EX ld sqdhypot_d(int d, const hyperpoint& a, const hyperpoint& b) {
ld sum = 0;
for(int i=0; i<d; i++) sum += (a[i]-b[i])*(a[i]-b[i]);
return sum;
}
ld dhypot_d(int d, const hyperpoint& a, const hyperpoint& b) {
EX ld dhypot_d(int d, const hyperpoint& a, const hyperpoint& b) {
return sqrt(sqdhypot_d(d, a, b));
}
ld zlevel(const hyperpoint &h) {
EX ld zlevel(const hyperpoint &h) {
if(translatable) return h[GDIM];
else if(sphere) return sqrt(intval(h, Hypc));
else return (h[GDIM] < 0 ? -1 : 1) * sqrt(-intval(h, Hypc));
}
ld hypot_auto(ld x, ld y) {
EX ld hypot_auto(ld x, ld y) {
switch(cgclass) {
case gcEuclid:
return hypot(x, y);
@ -220,7 +220,7 @@ ld hypot_auto(ld x, ld y) {
}
// move H back to the sphere/hyperboloid/plane
hyperpoint normalize(hyperpoint H) {
EX hyperpoint normalize(hyperpoint H) {
ld Z = zlevel(H);
for(int c=0; c<MDIM; c++) H[c] /= Z;
return H;
@ -232,7 +232,7 @@ hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
}
// like mid, but take 3D into account
hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) {
EX hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) {
hyperpoint H3 = H1 + H2;
ld Z = 2;
@ -250,16 +250,16 @@ hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) {
// (just like isometries of the sphere are represented by rotation matrices)
// rotate by alpha degrees
transmatrix cspin(int a, int b, ld alpha) {
EX transmatrix cspin(int a, int b, ld alpha) {
transmatrix T = Id;
T[a][a] = +cos(alpha); T[a][b] = +sin(alpha);
T[b][a] = -sin(alpha); T[b][b] = +cos(alpha);
return T;
}
transmatrix spin(ld alpha) { return cspin(0, 1, alpha); }
EX transmatrix spin(ld alpha) { return cspin(0, 1, alpha); }
transmatrix random_spin() {
EX transmatrix random_spin() {
if(WDIM == 2) return spin(randd() * 2 * M_PI);
else {
ld alpha2 = acos(randd() * 2 - 1);
@ -269,25 +269,25 @@ transmatrix random_spin() {
}
}
transmatrix eupush(ld x, ld y) {
EX transmatrix eupush(ld x, ld y) {
transmatrix T = Id;
T[0][GDIM] = x;
T[1][GDIM] = y;
return T;
}
transmatrix eupush(hyperpoint h) {
EX transmatrix eupush(hyperpoint h) {
if(nonisotropic) return nisot::translate(h);
transmatrix T = Id;
for(int i=0; i<GDIM; i++) T[i][GDIM] = h[i];
return T;
}
transmatrix eupush3(ld x, ld y, ld z) {
EX transmatrix eupush3(ld x, ld y, ld z) {
return eupush(point3(x, y, z));
}
transmatrix euscalezoom(hyperpoint h) {
EX transmatrix euscalezoom(hyperpoint h) {
transmatrix T = Id;
T[0][0] = h[0];
T[0][1] = -h[1];
@ -296,14 +296,14 @@ transmatrix euscalezoom(hyperpoint h) {
return T;
}
transmatrix euaffine(hyperpoint h) {
EX transmatrix euaffine(hyperpoint h) {
transmatrix T = Id;
T[0][1] = h[0];
T[1][1] = exp(h[1]);
return T;
}
transmatrix cpush(int cid, ld alpha) {
EX transmatrix cpush(int cid, ld alpha) {
transmatrix T = Id;
if(nonisotropic)
return eupush3(cid == 0 ? alpha : 0, cid == 1 ? alpha : 0, cid == 2 ? alpha : 0);
@ -314,9 +314,9 @@ transmatrix cpush(int cid, ld alpha) {
}
// push alpha units to the right
transmatrix xpush(ld alpha) { return cpush(0, alpha); }
EX transmatrix xpush(ld alpha) { return cpush(0, alpha); }
bool eqmatrix(transmatrix A, transmatrix B, ld eps) {
EX bool eqmatrix(transmatrix A, transmatrix B, ld eps IS(.01)) {
for(int i=0; i<MDIM; i++)
for(int j=0; j<MDIM; j++)
if(std::abs(A[i][j] - B[i][j]) > 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; j<MDIM; j++)
T[j][i] = H[j];
}
transmatrix build_matrix(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint h4) {
EX transmatrix build_matrix(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint h4) {
transmatrix T;
for(int i=0; i<MDIM; i++)
T[i][0] = h1[i],
@ -448,14 +448,14 @@ transmatrix build_matrix(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint
}
// reverse of spintox(H)
transmatrix rspintox(const hyperpoint& H) {
EX transmatrix rspintox(const hyperpoint& H) {
if(GDIM == 2) return rspintoc(H, 0, 1);
transmatrix T1 = spintoc(H, 0, 1);
return rspintoc(H, 0, 1) * rspintoc(T1*H, 0, 2);
}
// for H such that H[1] == 0, this matrix pushes H to C0
transmatrix pushxto0(const hyperpoint& H) {
EX transmatrix pushxto0(const hyperpoint& H) {
transmatrix T = Id;
T[0][0] = +H[GDIM]; T[0][GDIM] = -H[0];
T[GDIM][0] = curvature() * H[0]; T[GDIM][GDIM] = +H[GDIM];
@ -463,14 +463,14 @@ transmatrix pushxto0(const hyperpoint& H) {
}
// reverse of pushxto0(H)
transmatrix rpushxto0(const hyperpoint& H) {
EX transmatrix rpushxto0(const hyperpoint& H) {
transmatrix T = Id;
T[0][0] = +H[GDIM]; T[0][GDIM] = H[0];
T[GDIM][0] = -curvature() * H[0]; T[GDIM][GDIM] = +H[GDIM];
return T;
}
transmatrix ggpushxto0(const hyperpoint& H, ld co) {
EX transmatrix ggpushxto0(const hyperpoint& H, ld co) {
if(translatable) {
return eupush(co * H);
}
@ -490,18 +490,18 @@ transmatrix ggpushxto0(const hyperpoint& H, ld co) {
}
// generalization: H[1] can be non-zero
transmatrix gpushxto0(const hyperpoint& H) {
EX transmatrix gpushxto0(const hyperpoint& H) {
return ggpushxto0(H, -1);
}
transmatrix rgpushxto0(const hyperpoint& H) {
EX transmatrix rgpushxto0(const hyperpoint& H) {
return ggpushxto0(H, 1);
}
// fix the matrix T so that it is indeed an isometry
// (without using this, imprecision could accumulate)
void fixmatrix(transmatrix& T) {
EX void fixmatrix(transmatrix& T) {
if(nonisotropic) ; // T may be inverse... do not do that
else if(euclid) {
for(int x=0; x<GDIM; x++) for(int y=0; y<=x; y++) {
@ -527,7 +527,7 @@ void fixmatrix(transmatrix& T) {
// show the matrix on screen
ld det(const transmatrix& T) {
EX ld det(const transmatrix& T) {
if(GDIM == 2) {
ld det = 0;
for(int i=0; i<3; i++)
@ -561,7 +561,7 @@ void inverse_error(const transmatrix& T) {
println(hlog, "Warning: inverting a singular matrix: ", T);
}
transmatrix inverse(const transmatrix& T) {
EX transmatrix inverse(const transmatrix& T) {
if(GDIM == 2) {
ld d = det(T);
transmatrix T2;
@ -612,7 +612,7 @@ transmatrix inverse(const transmatrix& T) {
}
// distance between mh and 0
ld hdist0(const hyperpoint& mh) {
EX ld hdist0(const hyperpoint& mh) {
switch(cgclass) {
case gcHyperbolic:
if(mh[GDIM] < 1) return 0;
@ -630,7 +630,7 @@ ld hdist0(const hyperpoint& mh) {
}
}
ld circlelength(ld r) {
EX ld circlelength(ld r) {
switch(cgclass) {
case gcEuclid:
return 2 * M_PI * r;
@ -644,7 +644,7 @@ ld circlelength(ld r) {
}
// distance between two points
ld hdist(const hyperpoint& h1, const hyperpoint& h2) {
EX ld hdist(const hyperpoint& h1, const hyperpoint& h2) {
// return hdist0(gpushxto0(h1) * h2);
ld iv = intval(h1, h2);
switch(cgclass) {
@ -662,7 +662,7 @@ ld hdist(const hyperpoint& h1, const hyperpoint& h2) {
}
}
hyperpoint mscale(const hyperpoint& t, double fac) {
EX hyperpoint mscale(const hyperpoint& t, double fac) {
if(GDIM == 3) return cpush(2, fac) * t;
hyperpoint res;
for(int i=0; i<MDIM; i++)
@ -670,7 +670,7 @@ hyperpoint mscale(const hyperpoint& t, double fac) {
return res;
}
transmatrix mscale(const transmatrix& t, double fac) {
EX transmatrix mscale(const transmatrix& t, double fac) {
if(GDIM == 3) {
// if(pmodel == mdFlatten) { transmatrix u = t; u[2][DIM] -= fac; return u; }
return t * cpush(2, fac);
@ -681,14 +681,14 @@ transmatrix mscale(const transmatrix& t, double fac) {
return res;
}
transmatrix xyscale(const transmatrix& t, double fac) {
EX transmatrix xyscale(const transmatrix& t, double fac) {
transmatrix res;
for(int i=0; i<MDIM; i++) for(int j=0; j<GDIM; j++)
res[i][j] = t[i][j] * fac;
return res;
}
transmatrix xyzscale(const transmatrix& t, double fac, double facz) {
EX transmatrix xyzscale(const transmatrix& t, double fac, double facz) {
transmatrix res;
for(int i=0; i<MDIM; i++) for(int j=0; j<GDIM; j++)
res[i][j] = t[i][j] * fac;
@ -699,7 +699,7 @@ transmatrix xyzscale(const transmatrix& t, double fac, double facz) {
// double downspin_zivory;
transmatrix mzscale(const transmatrix& t, double fac) {
EX transmatrix mzscale(const transmatrix& t, double fac) {
if(GDIM == 3) return t * cpush(2, fac);
// take only the spin
transmatrix tcentered = gpushxto0(tC0(t)) * t;
@ -713,7 +713,7 @@ transmatrix mzscale(const transmatrix& t, double fac) {
return res;
}
transmatrix pushone() { return xpush(sphere?.5 : 1); }
EX transmatrix pushone() { return xpush(sphere?.5 : 1); }
bool operator == (hyperpoint h1, hyperpoint h2) {
for(int i=0; i<MDIM; i++) if(h1[i] != h2[i]) return false;
@ -722,7 +722,7 @@ bool operator == (hyperpoint h1, hyperpoint h2) {
// rotation matrix in R^3
transmatrix rotmatrix(double rotation, int c0, int c1) {
EX transmatrix rotmatrix(double rotation, int c0, int c1) {
transmatrix t = Id;
t[c0][c0] = cos(rotation);
t[c1][c1] = cos(rotation);
@ -731,21 +731,21 @@ transmatrix rotmatrix(double rotation, int c0, int c1) {
return t;
}
hyperpoint mid3(hyperpoint h1, hyperpoint h2, hyperpoint h3) {
EX hyperpoint mid3(hyperpoint h1, hyperpoint h2, hyperpoint h3) {
return mid(h1+h2+h3, h1+h2+h3);
}
hyperpoint mid_at(hyperpoint h1, hyperpoint h2, ld v) {
EX hyperpoint mid_at(hyperpoint h1, hyperpoint h2, ld v) {
hyperpoint h = h1 * (1-v) + h2 * v;
return mid(h, h);
}
hyperpoint mid_at_actual(hyperpoint h, ld v) {
EX hyperpoint mid_at_actual(hyperpoint h, ld v) {
return rspintox(h) * xpush0(hdist0(h) * v);
}
// in 3D, an orthogonal projection of C0 on the given triangle
hyperpoint orthogonal_of_C0(hyperpoint h0, hyperpoint h1, hyperpoint h2) {
EX hyperpoint orthogonal_of_C0(hyperpoint h0, hyperpoint h1, hyperpoint h2) {
h0 /= h0[3];
h1 /= h1[3];
h2 /= h2[3];
@ -759,34 +759,34 @@ hyperpoint orthogonal_of_C0(hyperpoint h0, hyperpoint h1, hyperpoint h2) {
return normalize(h);
}
hyperpoint zshift(hyperpoint x, ld z) {
EX hyperpoint zshift(hyperpoint x, ld z) {
if(DIM == 3 && WDIM == 2) return rgpushxto0(x) * cpush0(2, z);
else return mscale(x, z);
}
hyperpoint hpxd(ld d, ld x, ld y, ld z) {
EX hyperpoint hpxd(ld d, ld x, ld y, ld z) {
hyperpoint H = hpxyz(d*x, d*y, z);
H = mid(H, H);
return H;
}
ld signum(ld x) { return x<0?-1:x>0?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;

View File

@ -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;

View File

@ -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<DIM; i++) for(int j=0; j<DIM; j++)
if(std::isnan(T[i][j]) || T[i][j] > 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<ld> 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<ld> bw;
bandfixer(transmatrix& T) : bw(band_shift, band_shift) { fix_the_band(T); }
};
#endif
namespace dq {
queue<tuple<heptagon*, transmatrix, ld>> 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;

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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<string> 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); }
}

View File

@ -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);
}

View File

@ -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<named_functionality()> *hooks_o_key;
#if HDR
typedef pair<string, reaction_t> 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<named_functionality()> *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;

View File

@ -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; i<ittypes; i++) if(itemclass(eItem(i)) == IC_ORB && items[i]) return true;
if(quotient) for(int i=0; i<isize(dcal); i++) {
cell *c = dcal[i];
@ -275,7 +275,7 @@ bool haveOrbPower() {
return false;
}
bool haveKraken() {
EX bool haveKraken() {
for(int i=0; i<spherecells(); i++) {
cell *c = getDodecahedron(i)->c7;
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<<pattern_threecolor(c)) | (1<<pattern_threecolor(c->move(i)));

View File

@ -50,37 +50,38 @@ void gamedata::restoregame() {
gamedata_all(*this);
}
hookset<void(gamedata*)> *hooks_gamedata;
EX hookset<void(gamedata*)> *hooks_gamedata;
namespace gamestack {
EX namespace gamestack {
vector<gamedata> 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<bool> 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<int> 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<ld> xmax(current_display->xmax, 0.5 * (currently_loaded+1));
dynamicval<ld> 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<int> 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
}

View File

@ -130,7 +130,7 @@ const vector<orbinfo> 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<ittypes; t++)
if(itemclass(eItem(t)) == IC_TREASURE && items[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;

View File

@ -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; i<ittypes; i++)
lastorbused[i] = orbused[i], orbused[i] = false;
@ -159,7 +159,7 @@ void reduceOrbPowers() {
items[itWarning] = 0;
}
void flashAlchemist(cell *c) {
EX void flashAlchemist(cell *c) {
if(isAlch(c)) {
if(isAlch(cwt.at))
c->wall = 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; i<isize(dcal); i++) {
@ -244,7 +244,7 @@ void activateFlashFrom(cell *cf, eMonster who, flagtype flags) {
}
}
bool distanceBound(cell *c1, cell *c2, int d) {
EX bool distanceBound(cell *c1, cell *c2, int d) {
if(!c1 || !c2) return false;
if(d == 0) return c1 == c2;
for(int i=0; i<c2->type; 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; i<isize(cl.lst); i++) {
@ -286,7 +286,7 @@ void checkFreedom(cell *cf) {
}
}
void activateFlash() {
EX void activateFlash() {
int tk = tkills();
for(int i=0; i<numplayers(); i++)
@ -303,14 +303,14 @@ void activateFlash() {
achievement_count("FLASH", tkills(), tk);
}
bool reflectingBarrierAt(cell *c) {
EX bool reflectingBarrierAt(cell *c) {
return
c->wall == 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; i<c->type; 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; i<c->type; 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; i<isize(dcal); i++) {
@ -687,7 +687,7 @@ void telekinesis(cell *dest) {
if(!shmup::on) checkmoveO();
}
eMonster summonedAt(cell *dest) {
EX eMonster summonedAt(cell *dest) {
if(dest->monst) 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(; d<c->type; d++) if(c->move(d) && c->move(d)->cpdist < c->cpdist) break;
if(d<c->type) for(int e=d; e<d+c->type; 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)

View File

@ -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) {

View File

@ -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<vector<hyperpoint>>, vector<vector<ld>>> make_walls() {
EX pair<vector<vector<hyperpoint>>, vector<vector<ld>>> make_walls() {
vector<vector<hyperpoint>> kv;
vector<vector<ld>> 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) {

View File

@ -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);

View File

@ -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<race_cellinfo> rti;
vector<cell*> track;
EX vector<cell*> track;
map<cell*, int> 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<eLand> race_lands = {
EX vector<eLand> race_lands = {
laHunting,
laCrossroads,
laJungle,
@ -850,7 +850,7 @@ vector<string> 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);

View File

@ -126,7 +126,7 @@ SDL_Surface *renderbuffer::render() {
}
#endif
int current_rbuffer = -1;
EX int current_rbuffer = -1;
void renderbuffer::enable() {
#if CAP_GL

View File

@ -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 }
}

View File

@ -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<bool(eLand&)> *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<bool(eLand&)> *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<bool(const string& s, int vol)> *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<landtypes; i++)
if(music[i] && music[i] != music[cid]) {
Mix_Music *which = music[i];
@ -253,7 +253,7 @@ void reuse_music_memory() {
}
#else
void resetmusic() {}
EX void resetmusic() {}
#endif
#if CAP_COMMANDLINE

View File

@ -6,7 +6,7 @@
namespace hr {
bool game_active;
EX bool game_active;
bool cblind;
bool autocheat;
@ -20,7 +20,8 @@ int asteroids_generated, asteroid_orbs_generated;
time_t timerstart, savetime;
bool timerstopped;
int savecount;
bool showoff = false, doCross = false;
EX bool showoff = false;
EX bool doCross = false;
bool gamegen_failure;

View File

@ -24,17 +24,17 @@ int SDL_GetTicks() {
#endif
#endif
long double sqr(long double x) { return x*x; }
string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; }
EX long double sqr(long double x) { return x*x; }
EX string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; }
string fts(ld x, int prec) {
EX string fts(ld x, int prec IS(6)) {
std::stringstream ss;
ss.precision(prec);
ss << x;
return ss.str();
}
string fts_fixed(ld x, int prec) {
EX string fts_fixed(ld x, int prec IS(6)) {
std::stringstream ss;
ss.precision(prec);
ss << std::fixed << x;
@ -70,41 +70,41 @@ string fts_smartdisplay(ld x, int maxdisplay) {
}
} */
string cts(char c) { char buf[8]; buf[0] = c; buf[1] = 0; return buf; }
string llts(long long i) {
EX string cts(char c) { char buf[8]; buf[0] = c; buf[1] = 0; return buf; }
EX string llts(long long i) {
// sprintf does not work on Windows IIRC
if(i < 0) return "-" + llts(-i);
if(i < 10) return its((int) i);
return llts(i/10) + its(i%10);
}
string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
string itsh2(int i) {static char buf[16]; sprintf(buf, "%02X", i); return buf; }
string itsh8(int i) {static char buf[16]; sprintf(buf, "%08X", i); return buf; }
EX string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
EX string itsh2(int i) {static char buf[16]; sprintf(buf, "%02X", i); return buf; }
EX string itsh8(int i) {static char buf[16]; sprintf(buf, "%08X", i); return buf; }
int gcd(int i, int j) {
EX int gcd(int i, int j) {
return i ? gcd(j%i, i) : j;
}
int gmod(int i, int j) {
EX int gmod(int i, int j) {
i %= j; if(i<0) i += j;
return i;
}
int gdiv(int i, int j) {
EX int gdiv(int i, int j) {
return (i - gmod(i, j)) / j;
}
ld frac(ld x) {
EX ld frac(ld x) {
x -= int(x);
if(x < 0) x++;
return x;
}
ld lerp(ld a0, ld a1, ld x) {
EX ld lerp(ld a0, ld a1, ld x) {
return a0 + (a1-a0) * x;
}
ld ilerp(ld a0, ld a1, ld x) {
EX ld ilerp(ld a0, ld a1, ld x) {
return (x-a0) / (a1-a0);
}
@ -148,13 +148,13 @@ void profile_info() {
purehookset hooks_tests;
string simplify(const string& s) {
EX string simplify(const string& s) {
string res;
for(char c: s) if(isalnum(c)) res += c;
return res;
}
bool appears(const string& haystack, const string& needle) {
EX bool appears(const string& haystack, const string& needle) {
return simplify(haystack).find(simplify(needle)) != string::npos;
}
@ -271,13 +271,13 @@ cld exp_parser::parse(int prio) {
return res;
}
ld parseld(const string& s) {
EX ld parseld(const string& s) {
exp_parser ep;
ep.s = s;
return real(ep.parse());
}
string parser_help() {
EX string parser_help() {
return XLAT("Functions available: %1",
"(a)sin(h), (a)cos(h), (a)tan(h), exp, log, abs, re, im, conj, let(t=...,...t...), floor, frac, e, i, pi, s, ms, mousex, mousey, mousez, shot [1 if taking screenshot/animation], to01, ifp(a,v,w) [if positive]");
}
@ -287,17 +287,17 @@ logger hlog;
// kz: utility for printing
// if it is close to 0, assume it is floating errors
ld kz(ld x) {
EX ld kz(ld x) {
if(abs(x) < 1e-6) return 0;
return x;
}
hyperpoint kz(hyperpoint h) {
EX hyperpoint kz(hyperpoint h) {
for(int d=0; d<MAXMDIM; d++) h[d] = kz(h[d]);
return h;
}
transmatrix kz(transmatrix h) {
EX transmatrix kz(transmatrix h) {
for(int d=0; d<MAXMDIM; d++)
for(int e=0; e<MAXMDIM; e++)
h[d][e] = kz(h[d][e]);