updated to 10.0c

This commit is contained in:
Zeno Rogue 2017-07-23 01:33:27 +02:00
parent ce5650a81f
commit 8cb8e2a3ec
45 changed files with 2384 additions and 1359 deletions

View File

@ -86,7 +86,7 @@ bool wrongMode(char flags) {
if(yendor::on) return true;
if(peace::on) return true;
if(tactic::on) return true;
#ifdef TOUR
#if CAP_TOUR
if(tour::on) return true;
#endif
if(chaosmode != (flags == 'C')) return true;
@ -106,7 +106,7 @@ void achievement_log(const char* s, char flags) {
if(achievementsReceived[i] == s) return;
achievementsReceived.push_back(s);
#ifndef NOSAVE
#if CAP_SAVE
remove_emergency_save();
FILE *f = fopen(scorefile, "at");
@ -124,20 +124,16 @@ void achievement_log(const char* s, char flags) {
#endif
}
#ifdef STEAM
#if ISSTEAM
void improveItemScores();
#include "private/hypersteam.cpp"
#else
#ifndef ANDROID
#ifndef IOS
#elif !ISANDROID && !ISIOS
void achievement_init() {}
void achievement_close() {}
void achievement_gain(const char* s, char flags) {
achievement_log(s, flags);
}
#endif
#endif
#endif
void achievement_collection(eItem it, int prevgold, int newgold) {
if(cheater) return;
@ -213,7 +209,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
if(q == 8) achievement_gain("GRAIL4");
}
if(q == U10) {
if(q == (inv::on ? 25 : 10)) {
if(it == itDiamond) achievement_gain("DIAMOND2");
if(it == itRuby) achievement_gain("RUBY2");
if(it == itHyperstone) achievement_gain("HYPER2");
@ -269,7 +265,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
if(it == itBull) achievement_gain("BULL2");
}
if(q == R10) {
if(q == (inv::on ? 50 : 25)) {
if(it == itDiamond) achievement_gain("DIAMOND3");
if(it == itRuby) achievement_gain("RUBY3");
if(it == itHyperstone) achievement_gain("HYPER3");
@ -523,7 +519,7 @@ void achievement_final(bool really_final) {
#ifdef HAVE_ACHIEVEMENTS
upload_score(LB_STATISTICS, time(NULL));
if(cheater) return;
#ifdef TOUR
#if CAP_TOUR
if(tour::on) return;
#endif
@ -581,7 +577,7 @@ void achievement_final(bool really_final) {
}
if(total_improved >= 2) {
#ifndef ANDROID
#if !ISANDROID
addMessage(XLAT("Your total treasure has been recorded in the " LEADERFULL "."));
addMessage(XLAT("Congratulations!"));
#endif
@ -591,14 +587,14 @@ void achievement_final(bool really_final) {
else if(total_improved && specific_improved)
addMessage(XLAT("You have improved your total and '%1' high score!", iinf[specific_what].name));
else if(total_improved) {
#ifndef ANDROID
#if !ISANDROID
addMessage(XLAT("You have improved your total high score on " LEADER ". Congratulations!"));
#endif
}
else if(specific_improved >= 2)
addMessage(XLAT("You have improved %1 of your specific high scores!", its(specific_improved)));
else if(specific_improved) {
#ifndef ANDROID
#if !ISANDROID
addMessage(XLAT("You have improved your '%1' high score on " LEADER "!", iinf[specific_what].name));
#endif
}
@ -658,7 +654,7 @@ void achievement_victory(bool hyper) {
if(improved) {
if(improved >= 4) {
if(!hyper) addMessage(XLAT("This is your first victory!"));
#ifndef ANDROID
#if !ISANDROID
addMessage(XLAT("This has been recorded in the " LEADERFULL "."));
#endif
addMessage(XLAT("The faster you get here, the better you are!"));
@ -700,12 +696,12 @@ void achievement_display() {
col /= 10; col *= 0x10101;
displayfr(vid.xres/2, vid.yres/4, 2, vid.fsize * 2, achievementMessage[0], col & 0xFFFF00, 8);
int w = 2 * vid.fsize;
#ifndef MOBILE
#if ISMOBILE==0
while(w>3 && textwidth(w, achievementMessage[1]) > vid.xres) w--;
#endif
displayfr(vid.xres/2, vid.yres/4 + vid.fsize*2, 2, w, achievementMessage[1], col, 8);
w = vid.fsize;
#ifndef MOBILE
#if ISMOBILE==0
while(w>3 && textwidth(w, achievementMessage[2]) > vid.xres) w--;
#endif
displayfr(vid.xres/2, vid.yres/4 + vid.fsize*4, 2, w, achievementMessage[2], col, 8);

View File

@ -2,15 +2,38 @@ int backcolor = 0;
int bordcolor = 0;
int forecolor = 0xFFFFFF;
#ifndef NOSDL
SDL_Surface *s;
int utfsize(char c) {
unsigned char cu = c;
if(cu < 128) return 1;
if(cu < 224) return 2;
if(cu < 0xF0) return 3;
return 4;
}
#ifndef NOTTF
bool eqs(const char* x, const char* y) {
return *y? *x==*y?eqs(x+1,y+1):false:true;
}
int getnext(const char* s, int& i) {
int siz = utfsize(s[i]);
// if(fontdeb) printf("s=%s i=%d siz=%d\n", s, i, siz);
if(siz == 1) return s[i++];
for(int k=0; k<NUMEXTRA; k++)
if(eqs(s+i, natchars[k])) {
i += siz; return 128+k;
}
printf("Unknown character in: '%s'\n", s);
i ++; return '?';
}
#if CAP_SDLTTF
TTF_Font *font[256];
#endif
#endif
#ifndef NOSDL
#if CAP_SDL
SDL_Surface *s;
int ZZ;
int& qpixel(SDL_Surface *surf, int x, int y) {
@ -31,15 +54,10 @@ int qpixel3(SDL_Surface *surf, int x, int y) {
}
#endif
#ifndef EXTERNALFONT
#ifndef NOTTF
#if CAP_SDLTTF
void loadfont(int siz) {
if(!font[siz]) {
#ifdef WEB
font[siz] = TTF_OpenFont("sans-serif", siz);
#else
font[siz] = TTF_OpenFont(HYPERPATH "DejaVuSans-Bold.ttf", siz);
#endif
font[siz] = TTF_OpenFont(ISWEB ? "sans-serif" : HYPERPATH "DejaVuSans-Bold.ttf", siz);
// Destination set by ./configure (in the GitHub repository)
#ifdef FONTDESTDIR
if (font[siz] == NULL) {
@ -54,38 +72,30 @@ void loadfont(int siz) {
}
#endif
int gl_width(int size, const char *s);
#if !ISFAKEMOBILE && !ISANDROID & !ISIOS
int textwidth(int siz, const string &str) {
if(size(str) == 0) return 0;
#ifdef NOTTF
#ifdef GL
return gl_width(siz, str.c_str());
#else
return 0;
#endif
#else
#if CAP_SDLTTF
loadfont(siz);
int w, h;
TTF_SizeUTF8(font[siz], str.c_str(), &w, &h);
// printf("width = %d [%d]\n", w, size(str));
return w;
#elif CAP_GL
return gl_width(siz, str.c_str());
#else
return 0;
#endif
}
#endif
int textwidth(int siz, const string &str);
#ifdef IOS
#if ISIOS
int textwidth(int siz, const string &str) {
return mainfont->getSize(str, siz / 36.0).width;
}
#endif
int darkenedby(int c, int lev) {
@ -111,11 +121,9 @@ int darkena(int c, int lev, int a) {
return (darkenedby(c, lev) << 8) + a;
}
#ifndef GL
#if !CAP_GL
void setcameraangle(bool b) { }
#endif
#ifdef GL
#else
bool cameraangle_on;
@ -224,12 +232,14 @@ void setGLProjection() {
}
else glDisable(GL_LINE_SMOOTH);
glLineWidth(vid.linewidth);
#if !ISMOBILE
if(vid.antialias & AA_POLY) {
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
}
else glDisable(GL_POLYGON_SMOOTH);
#endif
//glLineWidth(1.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -249,11 +259,7 @@ void setGLProjection() {
selectEyeGL(0);
}
#ifdef MOBILE
#define EXTERNALFONT
#endif
#ifndef EXTERNALFONT
#if CAP_GLFONT
struct glfont_t {
GLuint * textures; // Holds The Texture Id's
@ -281,16 +287,8 @@ void glError(const char* GLcall, const char* file, const int line) {
}
}
#ifdef NOTTF
#define FIXEDSIZE
#endif
#ifdef CREATEFONT
#define FIXEDSIZE
#endif
void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
#ifdef NOTTF
#if CAP_TABFONT
int otwidth, otheight, tpix[3000], tpixindex = 0;
loadCompressedChar(otwidth, otheight, tpix);
#else
@ -301,14 +299,14 @@ void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
int twidth = next_p2( otwidth );
int theight = next_p2( otheight );
#ifdef NOTTF
#if CAP_TABFONT
int expanded_data[twidth * theight];
#else
Uint16 expanded_data[twidth * theight];
#endif
for(int j=0; j <theight;j++) for(int i=0; i < twidth; i++) {
#ifdef NOTTF
#if CAP_TABFONT
expanded_data[(i+j*twidth)] = (i>=otwidth || j>=otheight) ? 0 : tpix[tpixindex++];
#else
expanded_data[(i+j*twidth)] =
@ -324,7 +322,7 @@ void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0,
#ifdef NOTTF
#if CAP_TABFONT
GL_RGBA, GL_UNSIGNED_BYTE,
#else
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
@ -340,6 +338,11 @@ void sdltogl(SDL_Surface *txt, glfont_t& f, int ch) {
void init_glfont(int size) {
if(glfont[size]) return;
DEBB(DF_INIT, (debugfile,"init GL font: %d\n", size));
#if !CAP_TABFONT
loadfont(size);
if(!font[size]) return;
#endif
glfont[size] = new glfont_t;
@ -351,10 +354,7 @@ void init_glfont(int size) {
if(0) for(int i=0; i<128+NUMEXTRA; i++)
printf("texture %d = %d\n", i, f.textures[i]);
#ifndef NOTTF
loadfont(size);
if(!font[size]) return;
#if !CAP_TABFONT
char str[2]; str[1] = 0;
SDL_Color white;
@ -367,7 +367,7 @@ void init_glfont(int size) {
if(ch<32) continue;
#ifdef NOTTF
#if CAP_TABFONT
sdltogl(NULL, f, ch);
#else
@ -380,13 +380,10 @@ void init_glfont(int size) {
txt = TTF_RenderUTF8_Blended(font[size], natchars[ch-128], white);
}
if(txt == NULL) continue;
#ifdef CREATEFONT
#if CAP_CREATEFONT
generateFont(ch, txt);
#endif
sdltogl(txt, f, ch);
#endif
#ifndef NOTTF
SDL_FreeSurface(txt);
#endif
}
@ -395,46 +392,18 @@ void init_glfont(int size) {
GLERR("initfont");
}
int utfsize(char c) {
unsigned char cu = c;
if(cu < 128) return 1;
if(cu < 224) return 2;
if(cu < 0xF0) return 3;
return 4;
}
bool eqs(const char* x, const char* y) {
return *y? *x==*y?eqs(x+1,y+1):false:true;
}
int getnext(const char* s, int& i) {
int siz = utfsize(s[i]);
// if(fontdeb) printf("s=%s i=%d siz=%d\n", s, i, siz);
if(siz == 1) return s[i++];
for(int k=0; k<NUMEXTRA; k++)
if(eqs(s+i, natchars[k])) {
i += siz; return 128+k;
}
printf("Unknown character in: '%s'\n", s);
i ++; return '?';
}
GLfloat tver[24];
int gl_width(int size, const char *s) {
int gsiz = size;
if(size > vid.fsize || size > 72) gsiz = 72;
#ifdef FIXEDSIZE
gsiz = 36;
#if CAP_FIXEDSIZE
gsiz = CAP_FIXEDSIZE;
#endif
init_glfont(gsiz);
#ifndef NOTTF
if(!font[gsiz]) return 0;
#endif
if(!glfont[gsiz]) return 0;
glfont_t& f(*glfont[gsiz]);
@ -452,15 +421,12 @@ bool gl_print(int x, int y, int shift, int size, const char *s, int color, int a
int gsiz = size;
if(size > vid.fsize || size > 72) gsiz = 72;
#ifdef FIXEDSIZE
gsiz = 36;
#if CAP_FIXEDSIZE
gsiz = CAP_FIXEDSIZE;
#endif
init_glfont(gsiz);
#ifndef NOTTF
if(!font[gsiz]) return false;
#endif
if(!glfont[gsiz]) return false;
glfont_t& f(*glfont[gsiz]);
@ -561,7 +527,7 @@ purehookset hooks_resetGL;
void resetGL() {
DEBB(DF_INIT, (debugfile,"reset GL\n"));
callhooks(hooks_resetGL);
#ifndef EXTERNALFONT
#if CAP_GLFONT
for(int i=0; i<128; i++) if(glfont[i]) {
delete glfont[i];
glfont[i] = NULL;
@ -572,7 +538,62 @@ void resetGL() {
#endif
#ifndef MOBILE
#if CAP_XGD
vector<int> graphdata;
void gdpush(int t) {
graphdata.push_back(t);
}
bool displaychr(int x, int y, int shift, int size, char chr, int col) {
gdpush(2); gdpush(x); gdpush(y); gdpush(8);
gdpush(col); gdpush(size); gdpush(0);
gdpush(1); gdpush(chr);
return false;
}
void gdpush_utf8(const string& s) {
int g = (int) graphdata.size(), q = 0;
gdpush((int) s.size()); for(int i=0; i<size(s); i++) {
#if ISANDROID
unsigned char uch = (unsigned char) s[i];
if(uch >= 192 && uch < 224) {
int u = ((s[i] - 192)&31) << 6;
i++;
u += (s[i] - 128) & 63;
gdpush(u); q++;
}
else
#endif
{
gdpush(s[i]); q++;
}
}
graphdata[g] = q;
}
bool displayfr(int x, int y, int b, int size, const string &s, int color, int align) {
gdpush(2); gdpush(x); gdpush(y); gdpush(align);
gdpush(color); gdpush(size); gdpush(b);
gdpush_utf8(s);
int mx = mousex - x;
int my = mousey - y;
int len = textwidth(size, s);
return
mx >= -len*align/32 && mx <= +len*(16-align)/32 &&
my >= -size*3/4 && my <= +size*3/4;
}
bool displaystr(int x, int y, int shift, int size, const string &s, int color, int align) {
return displayfr(x,y,0,size,s,color,align);
}
bool displaystr(int x, int y, int shift, int size, char const *s, int color, int align) {
return displayfr(x,y,0,size,s,color,align);
}
#else
bool displaystr(int x, int y, int shift, int size, const char *str, int color, int align) {
if(strlen(str) == 0) return false;
@ -581,11 +602,11 @@ bool displaystr(int x, int y, int shift, int size, const char *str, int color, i
return false;
}
#ifdef GL
#if CAP_GLFONT
if(vid.usingGL) return gl_print(x, y, shift, size, str, color, align);
#endif
#ifdef NOTTF
#if !CAP_SDLTTF
static bool towarn = true;
if(towarn) towarn = false, printf("WARNING: NOTTF works only with OpenGL!\n");
return false;
@ -667,62 +688,6 @@ bool displaychr(int x, int y, int shift, int size, char chr, int col) {
buf[0] = chr; buf[1] = 0;
return displaystr(x, y, shift, size, buf, col, 8);
}
#else
vector<int> graphdata;
void gdpush(int t) {
graphdata.push_back(t);
}
bool displaychr(int x, int y, int shift, int size, char chr, int col) {
gdpush(2); gdpush(x); gdpush(y); gdpush(8);
gdpush(col); gdpush(size); gdpush(0);
gdpush(1); gdpush(chr);
return false;
}
void gdpush_utf8(const string& s) {
int g = (int) graphdata.size(), q = 0;
gdpush((int) s.size()); for(int i=0; i<s.size(); i++) {
#ifdef ANDROID
unsigned char uch = (unsigned char) s[i];
if(uch >= 192 && uch < 224) {
int u = ((s[i] - 192)&31) << 6;
i++;
u += (s[i] - 128) & 63;
gdpush(u); q++;
}
else
#endif
{
gdpush(s[i]); q++;
}
}
graphdata[g] = q;
}
bool displayfr(int x, int y, int b, int size, const string &s, int color, int align) {
gdpush(2); gdpush(x); gdpush(y); gdpush(align);
gdpush(color); gdpush(size); gdpush(b);
gdpush_utf8(s);
int mx = mousex - x;
int my = mousey - y;
int len = textwidth(size, s);
return
mx >= -len*align/32 && mx <= +len*(16-align)/32 &&
my >= -size*3/4 && my <= +size*3/4;
}
bool displaystr(int x, int y, int shift, int size, const string &s, int color, int align) {
return displayfr(x,y,0,size,s,color,align);
}
bool displaystr(int x, int y, int shift, int size, char const *s, int color, int align) {
return displayfr(x,y,0,size,s,color,align);
}
#endif
bool displaynum(int x, int y, int shift, int size, int col, int val, string title) {
@ -824,7 +789,7 @@ int gradient(int c0, int c1, ld v0, ld v, ld v1) {
void drawCircle(int x, int y, int size, int color) {
if(size < 0) size = -size;
#ifdef GL
#if CAP_GL
if(vid.usingGL) {
qglcoords = 0;
glcolor2(color);
@ -846,19 +811,15 @@ void drawCircle(int x, int y, int size, int color) {
}
#endif
#ifdef MOBILE
#if CAP_XGD
gdpush(4); gdpush(color); gdpush(x); gdpush(y); gdpush(size);
#else
#ifdef SDLGFX
#elif CAP_SDLGFX
((vid.antialias && AA_NOGL)?aacircleColor:circleColor) (s, x, y, size, color);
#else
#ifndef NOSDL
#elif CAP_SDL
int pts = size * 4;
if(pts > 1500) pts = 1500;
for(int r=0; r<pts; r++)
qpixel(s, x + int(size * sin(r)), y + int(size * cos(r))) = color;
#endif
#endif
#endif
}
@ -903,9 +864,7 @@ ld textscale() {
int pngres = 2000;
int pngformat = 0;
#ifndef NOSDL
#ifndef NOPNG
#if CAP_PNG
void IMAGESAVE(SDL_Surface *s, const char *fname) {
SDL_Surface *s2 = SDL_PNGFormatAlpha(s);
SDL_SavePNG(s2, fname);
@ -913,9 +872,10 @@ void IMAGESAVE(SDL_Surface *s, const char *fname) {
}
#endif
#if CAP_SDL
void saveHighQualityShot(const char *fname, const char *caption, int fade) {
#ifndef SDLGFX
#if !CAP_SDLGFX
addMessage(XLAT("High quality shots not available on this platform"));
return;
#endif
@ -944,7 +904,7 @@ void saveHighQualityShot(const char *fname, const char *caption, int fade) {
vid.usingGL = false;
// if(vid.pmodel == 0) vid.scale = 0.99;
calcparam();
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::fixparam();
#endif
@ -984,7 +944,7 @@ void saveHighQualityShot(const char *fname, const char *caption, int fade) {
}
#endif
#ifndef NOSDL
#if CAP_SDL
bool setfsize = true;
void setvideomode() {
@ -1000,7 +960,7 @@ void setvideomode() {
int flags = 0;
#ifdef GL
#if CAP_GL
if(vid.usingGL) {
flags = SDL_OPENGL | SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER;
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
@ -1008,12 +968,8 @@ void setvideomode() {
if(vid.antialias & AA_MULTI) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);
glEnable(GL_MULTISAMPLE);
}
#ifndef MAC
else
glDisable(GL_MULTISAMPLE);
#endif
}
#endif
@ -1035,8 +991,13 @@ void setvideomode() {
s = SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | SDL_RESIZABLE);
}
#ifdef GL
#if CAP_GL
if(vid.usingGL) {
if(vid.antialias & AA_MULTI)
glEnable(GL_MULTISAMPLE);
else
glDisable(GL_MULTISAMPLE);
glViewport(0, 0, vid.xres, vid.yres);
resetGL();
}
@ -1051,7 +1012,10 @@ void initgraph() {
DEBB(DF_INIT, (debugfile,"initgraph\n"));
initConfig();
#if CAP_SDLJOY
joyx = joyy = 0; joydir.d = -1;
#endif
restartGraph();
@ -1060,20 +1024,20 @@ void initgraph() {
buildpolys();
if(noGUI) {
#ifdef USE_COMMANDLINE
#if CAP_COMMANDLINE
arg::read(2);
#endif
return;
}
#ifndef NOSDL
#if CAP_SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) == -1)
{
printf("Failed to initialize video.\n");
exit(2);
}
#ifdef WEB
#if ISWEB
vid.xscr = vid.xres = 1200;
vid.yscr = vid.yres = 900;
#else
@ -1083,18 +1047,18 @@ void initgraph() {
#endif
SDL_WM_SetCaption("HyperRogue " VER, "HyperRogue " VER);
#endif
#endif
preparesort();
#ifndef NOCONFIG
#if CAP_CONFIG
loadConfig();
#endif
#ifdef USE_COMMANDLINE
#if CAP_COMMANDLINE
arg::read(2);
#endif
#ifndef NOSDL
#if CAP_SDL
setvideomode();
if(!s) {
printf("Failed to initialize graphics.\n");
@ -1103,37 +1067,37 @@ void initgraph() {
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_EnableUNICODE(1);
#endif
#ifndef NOTTF
#if CAP_SDLTTF
if(TTF_Init() != 0) {
printf("Failed to initialize TTF.\n");
exit(2);
}
#endif
initJoysticks();
#ifdef SDLAUDIO
#if CAP_SDLJOY
initJoysticks();
#endif
#if CAP_SDLAUDIO
initAudio();
#endif
#endif
#endif
}
void cleargraph() {
DEBB(DF_INIT, (debugfile,"clear graph\n"));
#ifndef NOTTF
#if CAP_SDLTTF
for(int i=0; i<256; i++) if(font[i]) TTF_CloseFont(font[i]);
#endif
#ifndef EXTERNALFONT
#ifdef GL
#if CAL_GLFONT
for(int i=0; i<128; i++) if(glfont[i]) delete glfont[i];
#endif
#endif
#ifndef NOSDL
#ifndef SIMULATE_JOYSTICK
#if CAP_SDLJOY
closeJoysticks();
#endif
#if CAP_SDL
SDL_Quit();
#endif
}

View File

@ -664,6 +664,11 @@ cell *cwpeek(cellwalker cw, int dir) {
return createMov(cw.c, (cw.spin+420+dir) % cw.c->type);
}
void cwmirrorat(cellwalker& cw, int d) {
cw.spin = (d+d - cw.spin + 420) % cw.c->type;
cw.mirrored = !cw.mirrored;
}
void cwstep(cellwalker& cw) {
createMov(cw.c, cw.spin);
int nspin = cw.c->spn(cw.spin);

View File

@ -1704,8 +1704,8 @@
- [RogueViz] fixed legend in the svg/high quality output
- more control for text in svg output
2017.07.04 14:40 work in progress
- peaceful mode (work in progress)
2017.07.16 21:05 version 10.0
- peaceful mode
- anti-aliased lines, and linewidth setting, option to make lines further from the model center narrower
- rearranged the menus
- '9' key to list all the frames in the current slideshow; better support for multiple slideshows compiled in
@ -1718,12 +1718,6 @@
- some preparation for the Inventory Mode
- texts changed, some minor translation fixes
- fixed the default wsad keys
- [technical] improved the NOGL compilation flag to avoid OpenGL
- [technical] refactoring (gotoHelp, sdltogl)
- [technical] changed #ifdef LOCAL to #ifdef EXTRA_...; extra features are now included by starting the compilation from another file
- [technical] HYPERPATH added, for reaching the files when HyperRogue is called from a different location
- [technical] private source files moved to the "private" dir
- antialiased multisampling
- major refactoring: return to previous menu
- image in the character selection screen
@ -1732,5 +1726,50 @@
- consistency in menu
- multiple selectable columns in scores
- menu -> scores => list the current game if in game over
- yendor hardness fix
- yendor/holygrail hardness fix
- hints shown on the quest status/quit screen
- long mirrors in the Mirror Land
- gravity destroys glyphs
- horns/bull now have different colors
- do not save princess in dungeon (and other gravity lands?)
- better love image
- controller works in menus
- better joystick axe configuration (no longer show up to seven players)
- on the esc-screen, the selection moves to 'continue' to prevent accidental quitting
- fixed Princess-related bugs (easier to find; squeak only once; no 'unknown princess'; saving with safety)
- inventory achievements
- double wall rate for Luck in the inventory mode
- slightly increased the charge count for Orb of Shielding and Orb of Freedom
- better config system
- replaced mtrand.cpp with the std implementation
- [technical] improved the NOGL compilation flag to avoid OpenGL
- [technical] refactoring (gotoHelp, sdltogl)
- [technical] changed #ifdef LOCAL to #ifdef EXTRA_...; extra features are now included by starting the compilation from another file
- [technical] HYPERPATH added, for reaching the files when HyperRogue is called from a different location
- [technical] private source files moved to the "private" dir
2017.07.1? ??:?? version 10.0a
- fixed a bug with achievements
- fixed a crash bug when restarting from the main menu
2017.07.21 23:59 version 10.0b
- more changes to the Hall of Mirrors: improved the Mimics, replaced the monsters
- made the Hall of Mirrors work in special modes (chaos, shmup, peace)
- multi-tile monster reflections are now animated
- fix crash bug when shifting modes
- fix crash bug with shmup mimics
- made the kill/treasure icons smaller
- removed the '!' marks on treasure in the Orb Strategy mode
- Orb of Discord no longer works o Krakens
- a bit higher mirroring for Orb of Earth
- fixed a bug with PTM desynchronization due to Mirror Land name change
- [technical] reworked the system of OS/capability compiler flags
2017.07.23 01:16 version 10.0c
- added missing descriptions
- updated the Czech translation
- Hall of Mirrors and LoEM are no longer forbidden to be adjacent
- fixed the Overview in the menu to go to the one appropriate for the current mode
- peaceful mode state is now displayed correctly in the main menu
- readded the sound when breaking mirrors
- fixed the vertical position of the flower in hand

View File

@ -335,7 +335,18 @@ const char *naturedesc =
"You can also target one of the cells adjacent to your ivy "
"(not to you) to grow or attack there.";
const int motypes = 139;
const char *mirroreddesc =
"A perfect mirror wall. It is unbreakable "
"and impassable "
"even for aethereal beings, and everything "
"you see inside is just an image of "
"the real world; you can swing your sword "
"at them, but that will not destroy them "
"in the real world. "
"Mirror walls reflect Mimics, lightning bolts, and "
"missiles perfectly.";
const int motypes = 141;
struct monstertype {
char glyph;
@ -393,13 +404,13 @@ monstertype minf[motypes] = {
{ 'M', 0x804000, "Giant Ape",
"This giant ape thinks that you are an enemy."},
{ 'B', 0x909000, "Slime Beast", slimehelp},
{ '@', 0x8080FF, "Mirror Image",
"A magical being which copies your movements."
},
{ '@', 0xFF8080, "Mirage",
{ '@', 0xFF80FF, "Mimic",
"A magical being which copies your movements. "
"You feel that it would be much more useful in an Euclidean space."
},
{ '@', 0xFF8080, "Mirage (REMOVED)",
"A magical being which copies your movements. "
},
{ '@', 0x509050, "Golem",
"You can summon these friendly constructs with a magical process."
},
@ -673,6 +684,18 @@ monstertype minf[motypes] = {
"Sleeping bulls wake up when you get into distance of two cells from them."
},
{ 'S', 0xFFD500, "Butterfly", bulldashdesc},
{ 'N', 0xFFFF80, "Narcissist",
"This person loves to look at their own reflection in the mirror. "
"He believes himself to be one of the most important creatures in this world, "
"and hates those who do not admire him."
},
{ 'M', 0xFFC0FF, "Mirror Spirit",
"A long time ago a mighty warrior was guarding the mirrors from being broken. "
"While this warrior is no longer alive, his reflections have gained life of "
"their own, and will punish the intruders.\n\n"
"If you attack a Mirror Spirit physically, it is delayed, but not destroyed -- "
"more reflections will come out of the mirror. Use Mimics to destroy them."
},
// shmup specials
{ '@', 0xC0C0C0, "Rogue", "In the Shoot'em Up mode, you are armed with thrown Knives."},
@ -700,7 +723,7 @@ enum eMonster {
moIvyRoot, moIvyHead, moIvyBranch, moIvyWait, moIvyNext, moIvyDead,
moMonkey,
moSlime,
moMirror, moMirage, moGolem, moGolemMoved,
moMimic, moREMOVED, moGolem, moGolemMoved,
moEagle, moSeep,
moZombie, moGhost, moNecromancer, moShadow,
moTentacle, moTentacletail, moTentaclewait, moTentacleEscaping,
@ -732,7 +755,7 @@ enum eMonster {
moKrakenH, moKrakenT, moDraugr, moFriendlyIvy,
moVampire, moBat, moReptile,
moHerdBull, moRagingBull, moSleepBull,
moButterfly,
moButterfly, moNarciss, moMirrorSpirit,
// shmup specials
moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball,
// temporary
@ -1378,7 +1401,7 @@ walltype winf[walltypes] = {
{ '.', 0xFFFF00, "Reptile floor", reptiledesc},
{ '.', 0xFFFF00, "Reptile bridge", reptiledesc},
{ '.', 0xFFFF00, "invisible floor", NODESCYET},
{ '#', 0xC0C0FF, "mirror wall", NODESCYET},
{ '#', 0xC0C0FF, "mirror wall", mirroreddesc},
};
enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCavefloor, waDeadTroll, waDune,
@ -1413,7 +1436,7 @@ enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCav
// --- land types ---
const int landtypes = 71;
const int landtypes = 72;
struct landtype {
int color;
@ -1446,7 +1469,10 @@ const landtype linf[landtypes] = {
},
{ 0x900090, "Alchemist Lab", slimehelp},
{ 0x704070, "Hall of Mirrors",
"A strange land which contains mirrors and mirages, protected by Mirror Rangers."},
"A strange land filled with mirrors. "
"Break magic mirrors and mirage clouds to "
"gain treasures and helpful Mimics."
},
{ 0x404070, "Graveyard",
"All the monsters you kill are carried to this strange land, and buried. "
"Careless Rogues are also carried here..."
@ -1587,10 +1613,12 @@ const landtype linf[landtypes] = {
{ 0x800080, "Bull Dash", bulldashdesc},
{ 0xC000C0, "Crossroads V", "Extremely narrow Crossroads layout.\n"},
{ 0xC0C0C0, "Cellular Automaton", cadesc},
{ 0xC0C0FF, "Mirror Wall", NODESCYET},
{ 0xC8C8FF, "Reflection", NODESCYET},
{ 0xC0C0FF, "Reflection", NODESCYET},
{ 0xC8C8FF, "Reflection", NODESCYET},
{ 0xC0C0FF, "Mirror Wall", mirroreddesc},
{ 0xC8C8FF, "Reflection", mirroreddesc},
{ 0xC0C0FF, "Reflection", mirroreddesc},
{ 0xC8C8FF, "Reflection", mirroreddesc},
{ 0xC8C8FF, "Mirror Land",
"A strange land which contains mirrors and mirages, protected by Mirror Rangers."},
};
enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle, laAlchemist, laMirror, laGraveyard,
@ -1608,7 +1636,8 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle
laKraken, laBurial, laTrollheim,
laHalloween, laDungeon, laMountain, laReptile,
laPrairie, laBull, laCrossroads5, laCA,
laMirrorWall, laMirrored, laMirrorWall2, laMirrored2
laMirrorWall, laMirrored, laMirrorWall2, laMirrored2,
laMirrorOld
};
// cell information for the game
@ -1695,7 +1724,7 @@ eLand land_over[LAND_OVERX] = {
eLand land_euc[LAND_EUC] = {
laIce, laCaves, laDesert, laMotion, laJungle,
laCrossroads,
laMirror, laMinefield, laAlchemist, laZebra, laPalace, laPrincessQuest,
laMirrorOld, laMinefield, laAlchemist, laZebra, laPalace, laPrincessQuest,
laOcean, laLivefjord, laWarpCoast, laCaribbean, laKraken, laWhirlpool, laRlyeh, laTemple,
laElementalWall, laTrollheim,
laDryForest, laWineyard, laDeadCaves, laGraveyard, laHive, laRedRock, laIvoryTower,
@ -1713,7 +1742,7 @@ eLand land_sph[LAND_SPH] = {
laHalloween,
laIce, laCaves, laDesert, laMotion, laJungle,
laCrossroads,
laMirror, laMinefield, laAlchemist,
laMirrorOld, laMinefield, laAlchemist,
laLivefjord, laWarpCoast, laKraken, laRlyeh,
laTrollheim,
laDryForest, laDeadCaves, laGraveyard, laHive, laRedRock,

View File

@ -592,7 +592,7 @@ namespace princess {
// printf("Improved dist to %d\n", newdist);
if(newdist == OUT_OF_PALACE) {
if(!princess::saved)
#ifdef INV
#if CAP_INV
if(!inv::on || !inv::usedForbidden)
#endif
achievement_gain("PRINCESS1");
@ -1010,9 +1010,21 @@ namespace whirlpool {
}
}
bool operator == (const cellwalker& c1, const cellwalker& c2) {
return c1.c == c2.c && c1.spin == c2.spin && c1.mirrored == c2.mirrored;
}
namespace mirror {
vector<pair<int, cellwalker>> mirrors;
static const int LIGHTNING = -1; // passed instead of cpid
bool noMirrorOn(cell *c) {
return c->monst || (!shmup::on && isPlayerOn(c)) || (geometry != gQuotient2 && geometry != gTorus && c->cpdist > 7);
}
bool cellMirrorable(cell *c) {
if(noMirrorOn(c)) return false;
return
c->wall == waNone || c->wall == waCavefloor || isAlchAny(c) ||
c->wall == waFrozenLake || c->wall == waDeadfloor || c->wall == waDeadfloor2 ||
@ -1021,55 +1033,64 @@ namespace mirror {
c->wall == waGargoyleBridge || c->wall == waTempFloor || c->wall == waTempBridge ||
c->wall == waMirrorWall;
}
inline eMonster switchtype(eMonster m) {
return (m == moMirror) ? moMirage : moMirror;
void destroyKilled() {
int j = 0;
for(int i=0; i<size(mirrors); i++)
if(mirrors[i].second.c->monst == moMimic)
mirrors[j++] = mirrors[i];
mirrors.resize(j);
}
void createMM(cellwalker& cw, eMonster type) {
if(type == moLightningBolt) {
castLightningBolt(cw);
return;
}
if(inmirror(cw)) {
bool b = cw.mirrored;
void unlist() {
for(auto& m: mirrors)
if(m.second.c->monst == moMimic)
m.second.c->monst = moNone;
}
void list() {
for(auto& m: mirrors)
m.second.c->monst = moMimic;
}
void destroyAll() {
unlist();
mirrors.clear();
}
void createMirror(cellwalker cw, int cpid) {
if(!shmup::on && inmirror(cw))
cw = reflect(cw);
if(cw.mirrored != b) type = switchtype(type);
}
if(cw.c->monst == moNone && cellMirrorable(cw.c) && !isPlayerOn(cw.c)) {
cw.c->monst = type;
cw.c->mondir = cw.spin;
cw.c->hitpoints = multi::cpid;
if(cpid == LIGHTNING)
castLightningBolt(cw);
else if(cellMirrorable(cw.c)) {
for(auto& m: mirrors)
if(m == make_pair(cpid,cw))
return;
mirrors.emplace_back(cpid, cw);
}
}
inline eMonster switchtypeif(eMonster m, bool b) {
if(!b) return m;
return (m == moMirror) ? moMirage : moMirror;
}
void createMirrors(cell *c, int dir, eMonster type) {
cellwalker C(c, dir);
void createMirrors(cellwalker cw, int cpid) {
cw.mirrored = !cw.mirrored;
cell *c = cw.c;
type = switchtype(type);
for(int i=0; i<c->type; i++) {
cwstep(C);
if(C.c->type == c->type) {
cwspin(C, i);
createMM(C, switchtypeif(type, C.mirrored));
cwspin(C, -i);
for(int i=0; i<cw.c->type; i++) {
cwstep(cw);
if(cw.c->type == c->type) {
cwspin(cw, i);
createMirror(cw, cpid);
cwspin(cw, -i);
}
cwstep(C);
cwspin(C, 1);
cwstep(cw);
cwspin(cw, 1);
}
}
void createMirages(cell *c, int dir, eMonster type) {
cellwalker C(c, dir);
void createMirages(cellwalker cw, int cpid) {
if(purehepta) {
for(int i=0; i<c->type; i++) {
cellwalker C2 = C;
for(int i=0; i<cw.c->type; i++) {
cellwalker C2 = cw;
cwstep(C2);
cwspin(C2, 3);
cwstep(C2);
@ -1077,156 +1098,138 @@ namespace mirror {
cwstep(C2);
cwspin(C2, 3);
cwspin(C2, -i);
createMM(C2, type);
cwspin(C, 1);
createMirror(C2, cpid);
cwspin(cw, 1);
}
return;
}
for(int i=0; i<6; i++) {
cwstep(C);
if(C.c->type == 6) {
cwspin(C, 2);
cwstep(C);
cwspin(C, 4-i);
createMM(C, type);
cwspin(C, 6-4+i);
cwstep(C);
cwspin(C, 2);
cwstep(C);
cwspin(C, 2-i);
createMM(C, type);
cwspin(C, 6-2+i);
cwstep(C);
cwspin(C, 2);
}
cwstep(C);
cwspin(C, 1);
}
}
void spin(int d) {
for(int i=0; i<size(mirrors); i++) {
cell *c = mirrors[i];
if(c->hitpoints != multi::cpid) continue;
if(c->monst == moMirror)
mirrors[i]->mondir = (mirrors[i]->mondir - d + 420) % mirrors[i]->type;
if(c->monst == moMirage)
mirrors[i]->mondir = (mirrors[i]->mondir + d + 420) % mirrors[i]->type;
}
}
void destroy() {
for(int i=0; i<size(mirrors); i++) {
cell *c = mirrors[i];
eMonster m = c->monst;
if(isMimic(m)) c->monst = moNone;
}
mirrors.clear();
}
void destroyStray() {
if(doall) return;
for(int i=0; i<size(mirrors2); i++) {
cell *c = mirrors2[i];
if(c->cpdist > 7 && isMimic(c)) {
c->monst = moNone;
cwstep(cw);
if(cw.c->type == 6) {
cwspin(cw, 2);
cwstep(cw);
cwspin(cw, 4-i);
createMirror(cw, cpid);
cwspin(cw, 6-4+i);
cwstep(cw);
cwspin(cw, 2);
cwstep(cw);
cwspin(cw, 2-i);
createMirror(cw, cpid);
cwspin(cw, 6-2+i);
cwstep(cw);
cwspin(cw, 2);
}
cwstep(cw);
cwspin(cw, 1);
}
}
void createHere(cellwalker cw, int cpid) {
if(cw.c->wall == waCloud)
createMirages(cw, cpid);
if(cw.c->wall == waMirror)
createMirrors(cw, cpid);
}
void breakMirror(cellwalker cw, int pid) {
cell *c = cw.c;
if(c->wall == waMirror || c->wall == waCloud) {
drawParticles(c, winf[c->wall].color, 16);
playSound(c, "pickup-mirror", 50);
if(pid >= 0 && (cw.c->land == laMirror || cw.c->land == laMirrorOld)) {
dynamicval<int> d(multi::cpid, pid);
gainShard(cw.c, c->wall == waMirror ? "The mirror shatters!" : "The cloud turns into a bunch of images!");
}
c->wall = waNone;
}
}
bool isKilledByMirror(cell *c) {
for(auto& m: mirrors)
if(cwpeek(m.second, 0) == c && canAttack(m.second.c, moMimic, c, c->monst, 0))
return true;
return false;
}
void go(bool fwd) {
int tk = tkills();
int nummirage = 0;
mirrors2.clear();
int nummirage = 0;
int j = 0;
for(int i=0; i<size(mirrors); i++) {
cell *c = mirrors[i];
if(c->hitpoints != multi::cpid) continue;
eMonster m = c->monst;
if(isMimic(m)) {
int dir = c->mondir;
if(m == moMirage) nummirage++;
cell *c2 = c->mov[dir];
if(c2 && inmirror(c2)) {
if(c->land == laMirror) {
// c->mondir = (dir+3) % 6;
c->monst = switchtype(m);
continue;
}
cellwalker cw(c2, c->spin(dir), false);
cw = reflect(cw);
dir = c->mondir = cw.c->spin(cw.spin);
if(cw.mirrored) m = c->monst = switchtype(m);
c2 = c->mov[dir];
auto& m = mirrors[i];
bool survive = true;
if(m.first == multi::cpid) {
cell *c = m.second.c;
if(!m.second.mirrored) nummirage++;
auto cw2 = m.second;
cwstep(cw2);
if(inmirror(cw2)) cw2 = reflect(cw2);
cell *c2 = cw2.c;
if(c2->monst) {
c->monst = moMimic;
if(!peace::on && canAttack(c,moMimic,c2,c2->monst, 0))
attackMonster(c2, AF_MSG | AF_ORSTUN, moMimic);
c->monst = moNone;
}
if(c2 && !isMimic(c2) && canAttack(c,m,c2,c2->monst, 0))
attackMonster(c2, AF_MSG | AF_ORSTUN, m);
if(c2->wall == waBigTree)
c2->wall = waSmallTree;
else if(c2->wall == waSmallTree)
c2->wall = waNone;
if(!fwd) continue;
c->monst = moNone;
if(!c2) continue;
if(!passable(c2, c, P_MONSTER | P_MIRROR | P_MIRRORWALL)) continue;
if(isWorm(c2)) continue;
if(c2->monst == moGreater) {
c2->monst = moLesser; continue;
}
if(c2->monst == moGreaterM) {
c2->monst = moLesserM; continue;
}
if(isPlayerOn(c2)) {
addMessage(XLAT("You join %the1.", m));
playSound(c2, "click");
continue;
}
if(isMimic(c2)) {
addMessage(XLAT("Two of your images crash and disappear!"));
playSound(c2, "click");
if(fwd) {
if(noMirrorOn(c2) || !passable(c2, c, P_MONSTER | P_MIRROR | P_MIRRORWALL)) {
survive = false;
continue;
}
c->monst = moMimic;
moveMonster(c2, c);
c2->monst = moNone;
continue;
empathyMove(c, c2, neighborId(c2, c));
m.second = cw2;
}
if(isIvy(c2) || c2->monst) {
// killIvy(c2);
continue;
}
c->monst = m; moveMonster(c2, c);
empathyMove(c, c2, dir);
mirrors2.push_back(c2);
if(c->mirror(dir) && isMimic(c2->monst))
c2->monst = switchtype(c2->monst);
}
}
for(int i=0; i<size(mirrors2); i++) {
cell *c = mirrors2[i];
if(c->hitpoints != multi::cpid) continue;
eMonster m = c->monst;
if(c->wall == waMirror) {
addMessage(XLAT("%The1 breaks the mirror!", m));
drawParticles(c, winf[c->wall].color, 16);
playSound(c, "pickup-mirror", 50);
createMirrors(c, c->mondir, m);
c->wall = waNone;
}
if(c->wall == waCloud) {
playSound(c, "pickup-mirror", 50);
drawParticles(c, winf[c->wall].color, 16);
addMessage(XLAT("%The1 disperses the cloud!", m));
createMirages(c, c->mondir, m);
c->wall = waNone;
}
if(survive) {
mirrors[j++] = m;
}
}
mirrors.resize(j);
achievement_count("MIRRORKILL", tkills(), tk);
achievement_count("MIRAGE", nummirage, 0);
}
void spingo(int d, bool fwd) {
if(multi::players > 1) spin(d);
go(fwd);
void act(int d, int flags) {
destroyKilled();
unlist();
if(multi::players == 1) multi::cpid = 0;
bool spinning =
flags & (multi::players > 1 ? SPINMULTI : SPINSINGLE);
if(spinning && d) {
for(auto& m: mirrors)
if(m.first == multi::cpid)
cwspin(m.second, d);
}
if(flags & ATTACK)
go(flags & GO);
list();
}
void breakAll() {
destroyKilled();
unlist();
if(numplayers() == 1)
createHere(cwt, 0);
else for(int i=0; i<numplayers(); i++)
createHere(multi::player[i], i);
for(int i=0; i<size(mirrors); i++)
createHere(mirrors[i].second, mirrors[i].first);
if(numplayers() == 1)
breakMirror(cwt, 0);
else for(int i=0; i<numplayers(); i++)
breakMirror(multi::player[i], i);
for(int i=0; i<size(mirrors); i++)
breakMirror(mirrors[i].second, -1);
list();
}
int mirrordir(cell *c) {
@ -1237,7 +1240,7 @@ namespace mirror {
if(createMov(c, i)->bardir == c->spin(i))
icount++, isum+=i;
}
if(icount > 1) return -1;
if(icount != 1) return -1;
return isum;
}
@ -1262,7 +1265,8 @@ namespace mirror {
if(!inmirror(cw)) break;
stepcount++; if(stepcount > 10000) {
if(debug) cw.c->wall = waBoat;
if(debug) printf("fail\n"); return cw;
if(debug) printf("fail\n");
return cw;
}
cell *c0 = cwpeek(cw, 0);
int go = 0;
@ -1337,14 +1341,20 @@ namespace mirror {
cw = traceback(v,cw).second;
return cw;
}
#if ISMOBILE==0
void debug() {
if(!mouseover) return;
queuemarkerat(gmatrix[mouseover], 0xFF0000FF);
#if CAP_SDL
cellwalker mw(mouseover, (SDL_GetTicks()/1000) % mouseover->type, (SDL_GetTicks()/500) % 2);
#else
cellwalker mw(mouseover, 0, 0);
#endif
mw = mirror::reflect(mw, true);
queuemarkerat(gmatrix[mw.c], 0x800000FF);
}
#endif
}
namespace hive {
@ -1882,6 +1892,7 @@ namespace heat {
for(int i=0; i<dcs; i++) {
cell *c = allcells[i];
if(!isIcyLand(c)) continue;
HEAT(c) += hmods[i] * rate;
if(c->monst == moCrystalSage && HEAT(c) >= SAGEMELT) {
addMessage(XLAT("%The1 melts away!", c->monst));
@ -2867,7 +2878,7 @@ namespace ca {
carule[i][1] = "00011000";
}
#ifdef USE_COMMANDLINE
#if CAP_COMMANDLINE
bool readArg() {
using namespace arg;
if(argis("-caprob")) {
@ -2919,7 +2930,7 @@ namespace ca {
auto ccm = addHook(clearmemory, 0, [] () {
offscreen.clear();
princess::clear();
mirrors.clear();
mirror::mirrors.clear();
clearing::bpdata.clear();
tortoise::emap.clear();
tortoise::babymap.clear();

View File

@ -150,7 +150,7 @@ void initcs(charstyle &cs) {
cs.uicolor = 0xFF0000FF;
}
#ifndef NOCONFIG
#if CAP_CONFIG
void savecs(FILE *f, charstyle& cs, int xvernum) {
int gflags = cs.charid;
if(vid.samegender) gflags |= 16;
@ -201,7 +201,7 @@ void initConfig() {
addsaver(vid.sspeed, "scrollingspeed", 0);
addsaver(vid.mspeed, "movement speed", 1);
addsaver(vid.full, "fullscreen", false);
addsaver(vid.aurastr, "aura strength", 128);
addsaver(vid.aurastr, "aura strength", ISMOBILE ? 0 : 128);
addsaver(vid.aurasmoothen, "aura smoothen", 5);
addsaver(vid.graphglyph, "graphical items/kills", 1);
addsaver(vid.particles, "extra effects", 1);
@ -218,8 +218,8 @@ void initConfig() {
addsaver(vid.yshift, "Y shift", 0);
addsaver(vid.camera_angle, "camera angle", 0);
addsaver(vid.ballproj, "ballproj", 1);
addsaver(vid.monmode, "monster display mode", (ISANDROID || ISPANDORA) ? 2 : 4);
addsaver(vid.wallmode, "wall display mode", (ISANDROID || ISPANDORA) ? 3 : 5);
addsaver(vid.monmode, "monster display mode", ISMOBILE ? 2 : 4);
addsaver(vid.wallmode, "wall display mode", ISMOBILE ? 3 : 5);
addsaver(geom3::depth, "3D depth");
addsaver(geom3::camera, "3D camera level");
@ -234,10 +234,12 @@ void initConfig() {
addsaver(geom3::highdetail, "3D highdetail");
addsaver(geom3::middetail, "3D middetail");
#if CAP_RUG
addsaver(rug::renderonce, "rug-renderonce");
addsaver(rug::rendernogl, "rug-rendernogl");
addsaver(rug::texturesize, "rug-texturesize");
addsaver(rug::scale, "rug-scale");
#endif
addsaverenum(pmodel, "used model");
addsaver(polygonal::SI, "polygon sides");
@ -308,7 +310,7 @@ void saveConfig() {
fprintf(f, "%s=%s\n", s->name.c_str(), s->save().c_str());
fclose(f);
#ifndef MOBILE
#if ISMOBILE==0
addMessage(s0 + "Configuration saved to: " + conffile);
#else
addMessage(s0 + "Configuration saved");
@ -323,7 +325,7 @@ void readf(FILE *f, ld& x) {
}
void loadOldConfig(FILE *f) {
int gl=1, aa=1, bb=1, cc, dd, ee;
int gl=1, aa=1, bb=1, cc, dd;
int err;
float a, b, c, d;
err=fscanf(f, "%f%f%f%f\n", &a, &b, &c, &d);
@ -351,11 +353,14 @@ void loadOldConfig(FILE *f) {
shmup::loadConfig(f);
aa = rug::renderonce; bb = rug::rendernogl; cc = purehepta; dd = chaosmode; ee = vid.steamscore;
#if CAP_RUG
aa = rug::renderonce; bb = rug::rendernogl; cc = purehepta; dd = chaosmode;
int ee = vid.steamscore;
double rs = rug::scale;
err=fscanf(f, "%d%d%d%d%lf%d%d", &aa, &bb, &rug::texturesize, &cc, &rs, &ee, &dd);
rug::renderonce = aa; rug::rendernogl = bb; purehepta = cc; chaosmode = dd; vid.steamscore = ee;
rug::scale = rs;
#endif
aa=conformal::includeHistory;
double ps = polygonal::STAR, lv = conformal::lvspeed;
@ -473,7 +478,7 @@ void loadConfig() {
void showAllConfig() {
dialog::addBreak(50);
dialog::addItem(XLAT("exit configuration"), 'v');
#ifndef NOCONFIG
#if CAP_CONFIG
dialog::addItem(XLAT("save the current config"), 's');
if(getcstat == 's')
mouseovers = XLAT("Config file: %1", conffile);
@ -485,7 +490,7 @@ void handleAllConfig(int sym, int uni) {
else if(uni == 'v') popScreen();
else if(sym == SDLK_ESCAPE) popScreen();
#ifndef NOCONFIG
#if CAP_CONFIG
else if(uni == 's') saveConfig();
#endif
}
@ -496,11 +501,9 @@ void showGraphConfig() {
dialog::init(XLAT("graphics configuration"));
#ifndef ONEGRAPH
#ifdef GL
#if CAP_GLORNOT
dialog::addBoolItem(XLAT("openGL mode"), vid.usingGL, 'o');
#endif
#endif
if(!vid.usingGL)
dialog::addBoolItem(XLAT("anti-aliasing"), vid.antialias & AA_NOGL, 'O');
@ -517,13 +520,13 @@ void showGraphConfig() {
// dialog::addBoolItem(XLAT("finer lines at the boundary"), vid.antialias & AA_LINEWIDTH, 'b');
}
#ifndef MOBWEB
#if CAP_FRAMELIMIT
dialog::addSelItem(XLAT("framerate limit"), its(vid.framelimit), 'l');
if(getcstat == 'l')
mouseovers = XLAT("Reduce the framerate limit to conserve CPU energy");
#endif
#ifndef IOS
#if !ISIOS && !ISWEB
dialog::addBoolItem(XLAT("fullscreen mode"), (vid.full), 'f');
#endif
@ -548,13 +551,13 @@ void showGraphConfig() {
dialog::addSelItem(XLAT("inventory/kill mode"), XLAT(glyphmodenames[vid.graphglyph]), 'd');
#ifdef MOBILE
#if ISMOBILE==1
dialog::addSelItem(XLAT("font scale"), its(fontscale), 'b');
#endif
dialog::addSelItem(XLAT("sight range"), its(sightrange), 'r');
#ifdef MOBILE
#if ISMOBILE==1
dialog::addSelItem(XLAT("compass size"), its(vid.mobilecompasssize), 'c');
#endif
@ -600,7 +603,7 @@ void showGraphConfig() {
if(xuni == 'f') switchFullscreen();
#ifndef ONEGRAPH
#if CAP_GLORNOT
if(xuni == 'o' && shiftmul > 0) switchGL();
#endif
@ -615,7 +618,9 @@ void showGraphConfig() {
vid.antialias |= AA_POLY;
else
vid.antialias |= AA_LINES;
#if CAP_SDL
setvideomode();
#endif
}
// if(xuni == 'b') vid.antialias ^= AA_LINEWIDTH;
@ -625,11 +630,13 @@ void showGraphConfig() {
if(xuni == 'c')
dialog::editNumber(vid.mobilecompasssize, 0, 100, 10, 20, XLAT("compass size"), "");
#if CAP_FRAMELIMIT
if(xuni == 'l')
dialog::editNumber(vid.framelimit, 5, 300, 10, 300, XLAT("framerate limit"), "");
#ifdef MOBILE
#endif
#if ISMOBILE
if(xuni =='b')
dialog::editNumber(fontscale, 0, 400, 10, 100, XLAT("font scale"), "");
#endif
@ -645,11 +652,11 @@ void showGraphConfig() {
void switchFullscreen() {
vid.full = !vid.full;
#ifdef ANDROID
#if ISANDROID
addMessage(XLAT("Reenter HyperRogue to apply this setting"));
settingsChanged = true;
#endif
#ifndef NOSDL
#if CAP_SDL
if(true) {
vid.xres = vid.full ? vid.xscr : 9999;
vid.yres = vid.full ? vid.yscr : 9999;
@ -664,15 +671,10 @@ void switchGL() {
vid.usingGL = !vid.usingGL;
if(vid.usingGL) addMessage(XLAT("openGL mode enabled"));
if(!vid.usingGL) addMessage(XLAT("openGL mode disabled"));
#ifndef ANDROID
if(!vid.usingGL) addMessage(XLAT("shift+O to switch anti-aliasing"));
#endif
#ifdef ANDROID
#if ISANDROID
settingsChanged = true;
#else
#ifndef NOSDL
#elif CAP_SDL
setvideomode();
#endif
#endif
}
@ -681,17 +683,15 @@ void showBasicConfig() {
const char *axmodes[5] = {"OFF", "auto", "light", "heavy", "arrows"};
dialog::init(XLAT("basic configuration"));
#ifndef NOTRANS
dialog::addSelItem(XLAT("language"), XLAT("EN"), 'l');
#endif
if(CAP_TRANS) dialog::addSelItem(XLAT("language"), XLAT("EN"), 'l');
dialog::addSelItem(XLAT("player character"), numplayers() > 1 ? "" : csname(vid.cs), 'g');
if(getcstat == 'g')
mouseovers = XLAT("Affects looks and grammar");
#ifndef NOAUDIO
dialog::addSelItem(XLAT("background music volume"), its(musicvolume), 'b');
dialog::addSelItem(XLAT("sound effects volume"), its(effvolume), 'e');
#endif
if(CAP_AUDIO) {
dialog::addSelItem(XLAT("background music volume"), its(musicvolume), 'b');
dialog::addSelItem(XLAT("sound effects volume"), its(effvolume), 'e');
}
// input:
dialog::addSelItem(XLAT("help for keyboard users"), XLAT(axmodes[vid.axes]), 'c');
@ -700,18 +700,19 @@ void showBasicConfig() {
dialog::addBoolItem(XLAT("draw circle around the target"), (vid.drawmousecircle), 'd');
dialog::addSelItem(XLAT("message flash time"), its(vid.flashtime), 't');
#ifdef MOBILE
#if ISMOBILE
dialog::addBoolItem(XLAT("targetting ranged Orbs long-click only"), (vid.shifttarget&2), 'i');
#else
dialog::addBoolItem(XLAT("targetting ranged Orbs Shift+click only"), (vid.shifttarget&1), 'i');
#endif
#ifdef STEAM
#if ISSTEAM
dialog::addBoolItem(XLAT("send scores to Steam leaderboards"), (vid.steamscore&1), 'l');
#endif
#ifndef MOBILE
dialog::addSelItem(XLAT("configure keys/joysticks"), "", 'p');
#endif
if(CAP_SHMUP && !ISMOBILE)
dialog::addSelItem(XLAT("configure keys/joysticks"), "", 'p');
showAllConfig();
@ -738,39 +739,36 @@ void showBasicConfig() {
if(uni >= 32 && uni < 64) xuni = uni;
if(xuni == 'c') { vid.axes += 60 + (shiftmul > 0 ? 1 : -1); vid.axes %= 5; }
#ifndef NOAUDIO
if(xuni == 'b') {
if(CAP_AUDIO && xuni == 'b') {
dialog::editNumber(musicvolume, 0, 128, 10, 60, XLAT("background music volume"), "");
}
if(xuni == 'e') {
if(CAP_AUDIO && xuni == 'e') {
dialog::editNumber(effvolume, 0, 128, 10, 60, XLAT("sound effects volume"), "");
}
#endif
#ifndef NOTRANS
if(xuni == 'l') {
if(CAP_TRANS && xuni == 'l') {
vid.language += (shiftmul>0?1:-1);
vid.language %= NUMLAN;
if(vid.language < 0) vid.language += NUMLAN;
#ifdef ANDROID
#if ISANDROID
settingsChanged = true;
#endif
}
#endif
if(xuni == 'g') pushScreen(showCustomizeChar);
#ifndef MOBILE
#if CAP_SHMUP
if(xuni == 'p') {
pushScreen(shmup::showShmupConfig);
multi::shmupcfg = shmup::on;
}
#endif
#endif
if(xuni == 'r') vid.revcontrol = !vid.revcontrol;
if(xuni == 'd') vid.drawmousecircle = !vid.drawmousecircle;
#ifdef STEAM
#if ISSTEAM
if(xuni == 'l') vid.steamscore = vid.steamscore^1;
#endif
if(xuni == 't')
@ -783,6 +781,7 @@ void showBasicConfig() {
};
}
#if CAP_SDLJOY
void showJoyConfig() {
gamescreen(4);
@ -791,7 +790,6 @@ void showJoyConfig() {
dialog::addSelItem(XLAT("first joystick position (movement)"), its(joyx)+","+its(joyy), 0);
dialog::addSelItem(XLAT("second joystick position (panning)"), its(panjoyx)+","+its(panjoyy), 0);
#ifndef MOBWEB
dialog::addSelItem(XLAT("joystick mode"), XLAT(autojoy ? "automatic" : "manual"), 'p');
if(getcstat == 'p') {
if(autojoy)
@ -804,7 +802,6 @@ void showJoyConfig() {
dialog::addSelItem(XLAT("first joystick: execute movement threshold"), its(vid.joyvalue2), 'b');
dialog::addSelItem(XLAT("second joystick: pan threshold"), its(vid.joypanthreshold), 'c');
dialog::addSelItem(XLAT("second joystick: panning speed"), fts(vid.joypanspeed * 1000), 'd');
#endif
dialog::addItem(XLAT("back"), 'v');
dialog::display();
@ -825,6 +822,7 @@ void showJoyConfig() {
else if(doexiton(sym, uni)) popScreen();
};
}
#endif
void projectionDialog() {
geom3::tc_alpha = ticks;

View File

@ -101,7 +101,7 @@ namespace polygonal {
}
#ifndef NOSDL
#if CAP_SDL
namespace spiral {
typedef long double ld;
@ -243,7 +243,7 @@ namespace conformal {
}
void progress(string str) {
#ifndef NOSDL
#if CAP_SDL
int tick = SDL_GetTicks();
if(tick > lastprogress + 250) {
lastprogress = tick;
@ -403,7 +403,7 @@ namespace conformal {
void restore();
void restoreBack();
#ifndef NOSDL
#if CAP_SDL
void createImage(bool dospiral) {
int segid = 1;
inHighQual = true;
@ -571,7 +571,7 @@ namespace conformal {
dialog::addBoolItem(XLAT("prepare the line animation"), (on), 'e');
if(on) dialog::addSelItem(XLAT("animation speed"), fts(lvspeed), 'a');
#ifndef NOSDL
#if CAP_SDL
dialog::addBoolItem(XLAT("render bands automatically"), (autoband), 'o');
if(autoband)
dialog::addBoolItem(XLAT("include history when auto-rendering"), (autobandhistory), 'j');
@ -649,7 +649,7 @@ namespace conformal {
else if(sym == 's')
dialog::editNumber(bandsegment, 500, 32000, 500, 16000, XLAT("band segment"), "");
else if(sym == 'g') { dospiral = !dospiral; }
#ifndef NOSDL
#if CAP_SDL
else if(uni == 'f' && pmodel == mdBand && on) createImage(dospiral);
#endif
else if(sym == 'i') {
@ -703,7 +703,7 @@ namespace conformal {
}
void renderAutoband() {
#ifndef NOSDL
#if CAP_SDL
if(!cwt.c || celldist(cwt.c) <= 7) return;
if(!autoband) return;
eModel spm = pmodel;

View File

@ -1,7 +1,7 @@
int frames;
bool outoffocus = false;
int mousex, mousey, joyx, joyy, panjoyx, panjoyy;
int mousex, mousey;
hyperpoint mouseh, mouseoh;
bool leftclick, rightclick, targetclick, hiliteclick, anyshiftclick, wheelclick,
@ -20,15 +20,20 @@ bool mousepressed = false;
bool mousemoved = false;
bool actonrelease = false;
#if CAP_SDLJOY
int joyx, joyy, panjoyx, panjoyy;
movedir joydir;
#endif
movedir mousedest;
ld shiftmul = 1;
cell *mouseover, *mouseover2, *lmouseover, *centerover;
ld modist, modist2, centdist;
movedir mousedest, joydir;
int lastt;
#ifdef WEB
#if ISWEB
Uint8 *SDL_GetKeyState(void *v) { static Uint8 tab[1024]; return tab; }
#endif
@ -125,7 +130,7 @@ void mousemovement() {
lmouseover = NULL;
}
#ifndef NOSDL
#if CAP_SDLJOY
SDL_Joystick* sticks[8];
int numsticks;
@ -206,16 +211,12 @@ bool doexiton(int sym, int uni) {
bool didsomething;
#ifdef MOBILE
typedef int eventtype;
#else
typedef SDL_Event eventtype;
#endif
void handlePanning(int sym, int uni) {
if(rug::rugged) return;
#ifndef PANDORA
#if !ISPANDORA
if(sym == SDLK_RIGHT) {
if(conformal::on)
conformal::lvspeed += 0.1 * shiftmul;
@ -286,7 +287,7 @@ void handleKeyNormal(int sym, int uni) {
if(sym == 'u' || sym == 'e' || sym == SDLK_KP9) movepckeydir(7);
}
#ifdef PANDORA
#if !ISPANDORA
if(DEFAULTCONTROL) {
if(sym == SDLK_RIGHT) movepckeydir(0);
if(sym == SDLK_LEFT) movepckeydir(4);
@ -345,7 +346,7 @@ void handleKeyNormal(int sym, int uni) {
}
if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
#ifdef INV
#if CAP_INV
if(uni == 'i' && DEFAULTNOR(sym) && inv::on)
pushScreen(inv::show);
#endif
@ -374,7 +375,7 @@ void handleKeyNormal(int sym, int uni) {
if(sym == SDLK_F1) gotoHelp(help);
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::processKey(sym, uni);
#endif
}
@ -386,7 +387,7 @@ void handlekey(int sym, int uni) {
keyhandler(sym, uni);
}
#ifdef NOSDL
#if !CAP_SDL
void mainloopiter() { printf("(compiled without SDL -- no action)\n"); quitmainloop = true; }
#else
@ -398,12 +399,10 @@ void mainloopiter() {
DEBB(DF_GRAPH, (debugfile,"main loop\n"));
#ifndef GFX
#ifndef GL
#if !CAP_SDLGFX && !CAP_GL
vid.wallmode = 0;
vid.monmode = 0;
#endif
#endif
optimizeview();
@ -429,7 +428,7 @@ void mainloopiter() {
if(cwt.mirrored) playerV = playerV * Mirror;
}
#ifdef WEB
#if ISWEB
if(playermoved && vid.sspeed > -4.99 && !outoffocus) {
centerpc((ticks - lastt) / 1000.0 * exp(vid.sspeed));
}
@ -479,7 +478,7 @@ void mainloopiter() {
targetclick = true;
}
#ifdef SDLAUDIO
#if CAP_SDLAUDIO
if(audio) handlemusic();
#endif
SDL_Event ev;
@ -517,9 +516,6 @@ void mainloopiter() {
extern bool setfsize;
setfsize = true;
setvideomode();
#ifdef GL
if(vid.usingGL) glViewport(0, 0, vid.xres, vid.yres);
#endif
}
if(ev.type == SDL_VIDEOEXPOSE) {
@ -655,7 +651,7 @@ void mainloopiter() {
mousex = ev.motion.x;
mousey = ev.motion.y;
#ifndef NORUG
#if CAP_RUG
if(rug::rugged)
mouseh = rug::gethyper(mousex, mousey);
else
@ -692,7 +688,7 @@ void mainloopiter() {
void mainloop() {
lastt = 0;
#ifdef WEB
#if ISWEB
initweb();
emscripten_set_main_loop(mainloopiter, 0, true);
#else
@ -700,7 +696,7 @@ void mainloop() {
#endif
}
#ifdef MOBILE
#if ISMOBILE==1
void displayabutton(int px, int py, string s, int col) {
// TMP
int siz = vid.yres > vid.xres ? vid.fsize*2 : vid.fsize * 3/2;

View File

@ -1,6 +1,6 @@
/* Missing.
#ifndef MOBILE
#if ISMOBILE==0
dialog::addItemHelp(16, XLAT("use Shift to decrease and Ctrl to fine tune "));
dialog::addItemHelp(17, XLAT("(e.g. Shift+Ctrl+Z)"));
#endif
@ -18,8 +18,8 @@ namespace dialog {
bool zoomoff = false;
};
#ifdef MENU_SCALING
#ifndef NOSDL
#if CAP_MENUSCALING
#if CAP_SDL
void handleZooming(SDL_Event &ev) {
using namespace zoom;
if(zoomoff || (cmode != emOverview && cmode != emTactic)) {
@ -241,10 +241,7 @@ namespace dialog {
void display() {
int N = items.size();
dfsize = vid.fsize;
#ifdef MOBILE
dfsize *= 3;
#endif
#ifdef PANDORA
#if ISMOBILE || ISPANDORA
dfsize *= 3;
#endif
dfspace = dfsize * 5/4;
@ -292,7 +289,7 @@ namespace dialog {
}
else if(I.type == diItem) {
bool xthis = (mousey >= top && mousey < tothei);
#ifdef MOBILE
#if ISMOBILE
if(xthis && mousepressed)
I.color = I.colorc;
#else
@ -327,7 +324,7 @@ namespace dialog {
}
void handleNavigation(int &sym, int &uni) {
#ifndef MOBILE
#if !ISMOBILE
if(uni == '\n' || uni == '\r' || sym == SDLK_KP5)
for(int i=0; i<size(items); i++)
if(items[i].type == diItem)
@ -529,16 +526,16 @@ namespace dialog {
if(kind == 'v') ne.s = fts(*ne.editwhat);
}
#ifndef NOAUDIO
#if CAP_AUDIO
if(ne.intval == &musicvolume) {
if(musicvolume < 0)
*ne.editwhat = musicvolume = 0, affect('v');
else if(musicvolume > MIX_MAX_VOLUME)
*ne.editwhat = musicvolume = MIX_MAX_VOLUME, affect('v');
#ifdef SDLAUDIO
#if CAP_SDLAUDIO
else Mix_VolumeMusic(musicvolume);
#endif
#ifdef ANDROID
#if ISANDROID
settingsChanged = true;
#endif
}
@ -548,7 +545,7 @@ namespace dialog {
*ne.editwhat = effvolume = 0, affect('v');
else if(effvolume > MIX_MAX_VOLUME)
*ne.editwhat = effvolume = MIX_MAX_VOLUME, affect('v');
#ifdef ANDROID
#if ISANDROID
settingsChanged = true;
#endif
}
@ -557,7 +554,7 @@ namespace dialog {
if(ne.intval == &vid.framelimit && vid.framelimit < 5)
*ne.editwhat = vid.framelimit = 5, affect('v');
#ifdef MOBILE
#if ISMOBILE==1
if(ne.intval == &fontscale && fontscale < 50)
*ne.editwhat = fontscale = 50, affect('v');
#endif
@ -603,7 +600,7 @@ namespace dialog {
if(cmode & sm::A3) {
buildpolys();
#ifdef GL
#if CAP_GL
resetGL();
#endif
}
@ -616,7 +613,7 @@ namespace dialog {
addInfo(ne.s);
addSlider(ne.scale(ne.vmin), ne.scale(*ne.editwhat), ne.scale(ne.vmax), 500);
addBreak(100);
#ifndef MOBILE
#if ISMOBILE==0
addHelp("You can scroll with arrow keys -- Ctrl to fine-tune");
addBreak(100);
#endif
@ -630,12 +627,7 @@ namespace dialog {
if(ne.help != "") {
addHelp(ne.help);
bool scal = size(ne.help) > 160;
#ifndef MOBILE
#ifndef PANDORA
scal = false;
#endif
#endif
bool scal = !ISMOBILE && !ISPANDORA && size(ne.help) > 160;
if(scal) lastItem().scale = 30;
}
@ -665,7 +657,7 @@ namespace dialog {
sscanf(ne.s.c_str(), LDF, ne.editwhat);
affect('s');
}
#ifndef MOBILE
#if !ISMOBILE
else if(sym == SDLK_RIGHT || sym == SDLK_KP6) {
if(ne.intval && abs(shiftmul) < .6)
(*ne.editwhat)++;

View File

@ -1,11 +1,6 @@
#define ISANDROID 0
#define ISMOBILE 1
#define ISIOS 0
#define MOBILE
#define ISFAKEMOBILE 1
#define MOBPAR_FORMAL int
#define MOBPAR_ACTUAL 0
#define FAKEMOBILE
#define ANDROIDSHARE
#define MIX_MAX_VOLUME 128
const char *scorefile = "fakemobile_score.txt";
@ -13,7 +8,6 @@ const char *conffile = "fakemobile_config.txt";
#include <SDL/SDL.h>
#include <GL/gl.h>
#include "init.cpp"
#include <SDL/SDL_ttf.h>
@ -21,6 +15,10 @@ const char *conffile = "fakemobile_config.txt";
#undef main
void playSound(cell *c, const string& fname, int vol) {
printf("Play sound: %s\n", fname.c_str());
}
SDL_Surface *s;
int gdpos = 0;
@ -107,7 +105,6 @@ int main(int argc, char **argv) {
}
int mx = 0; int my = 0; bool _clicked = false;
int action = 0;
firstland = laMinefield;
@ -129,13 +126,13 @@ int main(int argc, char **argv) {
action = 0;
gdpos = 0;
while(gdpos < graphdata.size()) {
while(gdpos < size(graphdata)) {
switch(gdpop()) {
case 2: {
int x = gdpop(), y = gdpop(), al = gdpop();
int color = gdpop();
int size = gdpop();
int b = gdpop();
gdpop();
int n = gdpop();
string s;
for(int i=0; i<n; i++) s += char(gdpop());
@ -213,9 +210,8 @@ int main(int argc, char **argv) {
items[itGreenStone] = 100;
}
action = sym; */
eventtype ex;
mousing = false;
handlekey(sym, sym, ex);
handlekey(sym, sym);
}
if(ev.type == SDL_QUIT) {

View File

@ -66,7 +66,11 @@ bool hasTimeout(cell *c) {
}
bool isMimic(eMonster m) {
return m == moMirror || m == moMirage;
return m == moMimic;
}
int mirrorcolor(bool mirrored) {
return mirrored ? 0x8080FF : 0xFF80C0;
}
bool isMimic(cell *c) {
@ -93,7 +97,7 @@ bool isGolemOrKnight(cell *c) { return isGolemOrKnight(c->monst); }
bool isNonliving(eMonster m) {
return
m == moMirage || m == moMirror || m == moGolem || m == moGolemMoved ||
m == moMimic || m == moGolem || m == moGolemMoved ||
m == moZombie || m == moGhost || m == moShadow || m == moSkeleton ||
m == moEvilGolem || m == moIllusion || m == moEarthElemental ||
m == moWaterElemental || m == moDraugr;
@ -355,6 +359,7 @@ bool normalMover(eMonster m) {
m == moOutlaw || m == moRedFox || m == moFalsePrincess || m == moRoseLady ||
m == moRoseBeauty || m == moWolf ||
m == moResearcher || m == moRagingBull ||
m == moNarciss || m == moMirrorSpirit ||
slowMover(m);
}

152
game.cpp
View File

@ -7,7 +7,7 @@ int lastsafety;
int mutantphase;
int turncount;
int rosewave, rosephase;
int avengers;
int avengers, mirrorspirits;
cell *lastmove;
enum eLastmovetype {lmSkip, lmMove, lmAttack, lmSpecial, lmPush, lmTree};
@ -46,6 +46,7 @@ flagtype havewhat, hadwhat;
#define HF_WARP (1<<20)
#define HF_MOUSE (1<<21)
#define HF_RIVER (1<<22)
#define HF_MIRROR (1<<23)
bool seenSevenMines = false;
@ -103,7 +104,7 @@ vector<cell*> pathqm; // list of monsters to move (pathq restriced to monsters)
vector<cell*> targets; // list of monster targets
// monsters of specific types to move
vector<cell*> worms, ivies, ghosts, golems, mirrors, mirrors2, hexsnakes;
vector<cell*> worms, ivies, ghosts, golems, hexsnakes;
vector<cell*> temps; // temporary changes during bfs
vector<eMonster> tempval; // restore temps
@ -270,7 +271,7 @@ int gold(int no) {
if(!(no & NO_GRAIL)) i += items[itHolyGrail] * 10;
if(!(no & NO_LOVE)) {
bool love = items[itOrbLove];
#ifdef INV
#if CAP_INV
if(inv::on && inv::remaining[itOrbLove])
love = true;
#endif
@ -865,6 +866,11 @@ bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags) {
if(m2 == moHedge && !(flags & (AF_STAB | AF_TOUGH | AF_EAT | AF_MAGIC | AF_LANCE | AF_SWORD_INTO | AF_HORNS | AF_BULL)))
if(!checkOrb(m1, itOrbThorns)) return false;
// krakens do not try to fight even with Discord
if((m1 == moKrakenT || m1 == moKrakenH) &&
(m2 == moKrakenT || m2 == moKrakenH))
return false;
if(m2 == moDraugr && !(flags & (AF_SWORD | AF_MAGIC | AF_SWORD_INTO | AF_HORNS))) return false;
// if(m2 == moHerdBull && !(flags & AF_MAGIC)) return false;
@ -955,7 +961,7 @@ bool stalemate1::isKilled(cell *w) {
if(canAttack(moveto, who, w, w->monst, AF_STAB))
return true;
if(who == moPlayer && (killed || moveto != comefrom) && mirrorkill(w)) return true;
if(who == moPlayer && (killed || moveto != comefrom) && mirror::isKilledByMirror(w)) return true;
if(w->monst == moIvyHead || w->monst == moIvyBranch || isMutantIvy(w))
return isChild(w, killed);
@ -999,13 +1005,6 @@ int neighborId(cell *ofWhat, cell *whichOne) {
// how many monsters are near
eMonster which;
bool mirrorkill(cell *c) {
for(int t=0; t<c->type; t++)
if(c->mov[t] && isMimic(c->mov[t]) && c->mov[t]->mov[c->mov[t]->mondir] == c)
return true;
return false;
}
bool flashWouldKill(cell *c, flagtype extra) {
for(int t=0; t<c->type; t++) {
cell *c2 = c->mov[t];
@ -1120,7 +1119,7 @@ int monstersnear(stalemate1& sm) {
}
// flashwitches cannot attack if it would kill another enemy
if(c3->monst == moWitchFlash && flashWouldKill(c3, 0)) continue;
if(stalemate::anyKilled() && mirrorkill(c3)) continue;
if(stalemate::anyKilled() && mirror::isKilledByMirror(c3)) continue;
res++, which = c3->monst;
}
@ -1722,6 +1721,11 @@ void killMonster(cell *c, eMonster who, flagtype deathflags) {
if(avenge) { avengers += 2; }
}
if(m == moMirrorSpirit && who != moMimic && !(deathflags & AF_MAGIC)) {
kills[m]--;
mirrorspirits++;
}
if(isMutantIvy(m) || m == moFriendlyIvy) {
pcount = 0;
killMutantIvy(c, who);
@ -2549,7 +2553,7 @@ void bfs() {
int dcs = size(dcal);
for(int i=0; i<dcs; i++) dcal[i]->cpdist = INFD;
worms.clear(); ivies.clear(); ghosts.clear(); golems.clear(); mirrors.clear();
worms.clear(); ivies.clear(); ghosts.clear(); golems.clear();
temps.clear(); tempval.clear(); targets.clear();
statuecount = 0;
hexsnakes.clear();
@ -2557,6 +2561,7 @@ void bfs() {
hadwhat = havewhat;
havewhat = 0;
if(!(hadwhat & HF_WARP)) { avengers = 0; }
if(!(hadwhat & HF_MIRROR)) { mirrorspirits = 0; }
elec::havecharge = false;
elec::afterOrb = false;
@ -2602,6 +2607,7 @@ void bfs() {
if(!c2) continue;
if(isWarped(c2->land)) havewhat |= HF_WARP;
if(c2->land == laMirror) havewhat |= HF_MIRROR;
if((c->wall == waBoat || c->wall == waSea) &&
(c2->wall == waSulphur || c2->wall == waSulphurC))
@ -2726,7 +2732,6 @@ void bfs() {
if(items[itOrbIllusion]) items[itOrbIllusion]--;
else c2->monst = moNone;
}
if(isMimic(c2)) mirrors.push_back(c2);
}
else if(c2->monst == moButterfly) {
addButterfly(c2);
@ -2765,12 +2770,6 @@ void bfs() {
buildAirmap();
if(overgenerate) doOvergenerate();
if(geometry == gQuotient2) {
mirrors.clear();
for(cell *c: currentmap->allcells())
if(isMimic(c)) mirrors.push_back(c);
}
}
bool makeEmpty(cell *c) {
@ -2928,7 +2927,7 @@ string itemcounter(int qty) {
void gainShard(cell *c2, const char *msg) {
invismove = false;
string s = XLAT(msg);
if(c2->land == laMirror) {
if(c2->land == laMirror && !peace::on) {
gainItem(itShard);
s += itemcounter(items[itShard]);
collectMessage(c2, itShard);
@ -2968,23 +2967,6 @@ void playerMoveEffects(cell *c1, cell *c2) {
drainOrb(itOrbAether, 2);
}
if(c2->wall == waMirror && !markOrb(itOrbAether)) {
drawParticles(c2, winf[c2->wall].color, 16);
gainShard(c2, "The mirror shatters!");
playSound(c2, "pickup-mirror");
cell *pc = multi::player[multi::cpid].c;
multi::player[multi::cpid].c = c2;
mirror::createMirrors(cwt.c, cwt.spin, moMirage);
multi::player[multi::cpid].c = pc;
}
if(c2->wall == waCloud && !markOrb(itOrbAether)) {
drawParticles(c2, winf[c2->wall].color, 16);
gainShard(c2, "The cloud turns into a bunch of images!");
playSound(c2, "pickup-mirror");
mirror::createMirages(cwt.c, cwt.spin, moMirage);
}
if(cellUnstable(c2) && !markOrb(itOrbAether)) doesFallSound(c2);
if(c2->wall == waStrandedBoat && markOrb(itOrbWater))
@ -3055,7 +3037,7 @@ void moveMonster(cell *ct, cell *cf) {
printf("called for Dragon\n");
return;
}
animateMovement(cf, ct, LAYER_SMALL);
if(m != moMimic) animateMovement(cf, ct, LAYER_SMALL);
// the following line is necessary because otherwise plates disappear only inside the sight range
if(cellUnstable(cf) && !ignoresPlates(m)) cf->wall = waChasm;
moveEffect(ct, cf, m);
@ -3303,7 +3285,7 @@ int moveval(cell *c1, cell *c2, int d, int mf) {
else return 2000;
}
if(isPlayerOn(c2)) return peace::on ? -1700 : 2500;
else if(isFriendlyOrBug(c2)) return 2000;
else if(isFriendlyOrBug(c2)) return peace::on ? -1600 : 2000;
else return 500;
}
@ -4007,7 +3989,8 @@ void groupmove2(cell *c, cell *from, int d, eMonster movtype, flagtype mf) {
if(!passable_for(movtype, from, c, P_ONPLAYER | P_MONSTER)) return;
if(!ignoresSmell(c->monst) && againstRose(c, from)) return;
if((mf & MF_ONLYEAGLE) && c->monst != moEagle && c->monst != moBat) return;
if((mf & MF_ONLYEAGLE) && c->monst != moEagle && c->monst != moBat)
return;
// in the gravity lands, eagles cannot ascend in their second move
if((mf & MF_ONLYEAGLE) && gravityLevel(c) < gravityLevel(from)) {
c->aitmp = sval; return;
@ -5334,7 +5317,7 @@ bool activateRecall() {
killFriendlyIvy();
movecost(cwt.c, recallCell);
playerMoveEffects(cwt.c, recallCell);
mirror::destroy();
mirror::destroyAll();
items[itOrbSword] = 0;
items[itOrbSword2] = 0;
@ -5409,7 +5392,7 @@ bool hasSafeOrb(cell *c) {
void checkmove() {
#ifdef INV
#if CAP_INV
if(inv::on) inv::compute();
#endif
@ -5437,7 +5420,7 @@ void checkmove() {
canmove = legalmoves[cwt.spin] = true;
if(kills[moPlayer]) canmove = false;
#ifdef INV
#if CAP_INV
if(!canmove && !inv::incheck) {
if(inv::remaining[itOrbSafety])
canmove = true;
@ -5530,7 +5513,7 @@ void movecost(cell* from, cell *to) {
addMessage(XLAT("As you leave, your powers are drained!"));
}
#ifdef TOUR
#if CAP_TOUR
if(from->land != to->land && tour::on)
tour::checkGoodLand(to->land);
#endif
@ -5734,7 +5717,7 @@ bool collectItem(cell *c2, bool telekinesis) {
playSound(c2, "pickup-orb"); // TODO summon
placeGolem(cwt.c, c2, moTameBomberbird);
}
#ifdef TOUR
#if CAP_TOUR
else if(tour::on && (c2->item == itOrbSafety || c2->item == itOrbRecall)) {
addMessage(XLAT("This Orb is not compatible with the Tutorial."));
return true;
@ -5854,7 +5837,7 @@ bool collectItem(cell *c2, bool telekinesis) {
chaosAchieved = true;
}
#ifdef MOBILE
#if ISMOBILE==1
if(pg < lastsafety + R30*3/2 && g2 >= lastsafety + R30*3/2)
addMessage(XLAT("The Orb of Safety from the Land of Eternal Motion might save you."));
#endif
@ -6167,11 +6150,11 @@ namespace orbbull {
}
void monstersTurn() {
mirror::breakAll();
DEBT("bfs");
bfs();
DEBT("charge");
if(elec::havecharge) elec::act();
mirror::destroyStray();
DEBT("mmo");
int phase2 = (1 & items[itOrbSpeed]);
if(!phase2) movemonsters();
@ -6335,7 +6318,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
int origd = d;
if(d >= 0) {
cwspin(cwt, d);
if(multi::players == 1) mirror::spin(d);
mirror::act(d, mirror::SPINSINGLE);
d = cwt.spin;
}
if(d != -1 && !checkonly) playermoved = true;
@ -6497,38 +6480,43 @@ bool movepcto(int d, int subdir, bool checkonly) {
goto statuejump;
}
if(c2->wall == waBigTree && !c2->monst && !markOrb(itOrbAether) && !nonAdjacentPlayer(cwt.c,c2)) {
bool attackable;
attackable =
c2->wall == waBigTree ||
c2->wall == waSmallTree ||
c2->wall == waMirrorWall;
attackable = attackable && (!c2->monst || isFriendly(c2));
if(attackable && markOrb(itOrbAether) && c2->wall != waMirrorWall)
attackable = false;
attackable = attackable && !nonAdjacentPlayer(cwt.c,c2);
if(attackable) {
if(checkNeedMove(checkonly, true)) return false;
if(monstersnear(cwt.c,NULL,moPlayer,NULL,cwt.c)) {
if(monstersnear(cwt.c,c2,moPlayer,NULL,cwt.c)) {
if(!checkonly && errormsgs) wouldkill("%The1 would get you!");
return false;
}
if(checkonly) return true;
drawParticles(c2, winf[c2->wall].color, 4);
addMessage(XLAT("You start chopping down the tree."));
playSound(c2, "hit-axe" + pick123());
if(survivalist && isHaunted(c2->land))
survivalist = false;
mirror::spingo(origd, 0);
c2->wall = waSmallTree;
lastmovetype = lmTree; lastmove = c2;
swordAttackStatic();
}
else if(c2->wall == waSmallTree && !c2->monst && !markOrb(itOrbAether) && !nonAdjacentPlayer(cwt.c,c2)) {
if(checkNeedMove(checkonly, true)) return false;
if(monstersnear(cwt.c,NULL,moPlayer,NULL,cwt.c)) {
if(!checkonly && errormsgs) wouldkill("%The1 would get you!");
return false;
if(c2->wall == waSmallTree) {
drawParticles(c2, winf[c2->wall].color, 4);
addMessage(XLAT("You start chopping down the tree."));
playSound(c2, "hit-axe" + pick123());
c2->wall = waNone;
}
else if(c2->wall == waBigTree) {
drawParticles(c2, winf[c2->wall].color, 8);
addMessage(XLAT("You chop down the tree."));
playSound(c2, "hit-axe" + pick123());
c2->wall = waSmallTree;
}
else {
if(!peace::on)
addMessage(XLAT("You swing your sword at the mirror."));
}
if(checkonly) return true;
drawParticles(c2, winf[c2->wall].color, 8);
addMessage(XLAT("You chop down the tree."));
playSound(c2, "hit-axe" + pick123());
if(survivalist && isHaunted(c2->land))
survivalist = false;
mirror::spingo(origd, 0);
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK);
lastmovetype = lmTree; lastmove = c2;
c2->wall = waNone;
swordAttackStatic();
}
else if(c2->monst == moKnight) {
@ -6616,6 +6604,8 @@ bool movepcto(int d, int subdir, bool checkonly) {
!c2->item);
} */
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK);
if(goodTortoise) {
items[itBabyTortoise] += 4;
updateHi(itBabyTortoise, items[itBabyTortoise]);
@ -6639,11 +6629,12 @@ bool movepcto(int d, int subdir, bool checkonly) {
}
else {
eMonster m = c2->monst;
attackMonster(c2, AF_MSG, moPlayer);
produceGhost(c2, m, moPlayer);
if(m) {
attackMonster(c2, AF_MSG, moPlayer);
produceGhost(c2, m, moPlayer);
}
}
mirror::spingo(origd, 0);
lastmovetype = lmAttack; lastmove = c2;
swordAttackStatic();
}
@ -6781,12 +6772,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
if(peace::on) pushpast |= c2->monst && !isMultitile(c2->monst);
if(isMimic(c2->monst)) {
addMessage(XLAT("You rejoin %the1.", c2->monst));
playSound(c2, "click");
killMonster(c2, moNone);
}
else if(pushpast) {
if(pushpast) {
bool pswitch = false;
if(c2->monst == moMouse)
princess::mouseSqueak(c2);
@ -6817,7 +6803,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
else
animateMovement(c1, cwt.c, LAYER_SMALL);
mirror::spingo(origd, 1);
mirror::act(origd, mirror::SPINMULTI | mirror::ATTACK | mirror::GO);
playerMoveEffects(c1, c2);
@ -6984,7 +6970,7 @@ bool mightBeMine(cell *c) {
}
void performMarkCommand(cell *c) {
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::mark(c);
#endif
if(c->land == laCA && c->wall == waNone)

247
graph.cpp
View File

@ -818,7 +818,7 @@ bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, dou
if(!shmup::on)
queuepoly(VBODY, (cs.charid >= 2 ? shSabre : shPSword), darkena(col, 0, 0XC0));
else if(shmup::curtime >= shmup::getPlayer()->nextshot)
else if(!where || shmup::curtime >= shmup::getPlayer()->nextshot)
queuepoly(VBODY, shPKnife, darkena(col, 0, 0XC0));
queuepoly(VHEAD, (cs.charid&1) ? shFemaleHair : shPHead, darkena(col, 1, 0XC0));
@ -904,7 +904,7 @@ bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, dou
}
else {
queuepoly(VHEAD, shPHead, 0xF0A0D0FF);
queuepoly(VHEAD, shFlowerHand, 0xC00000FF);
queuepoly(VBODY, shFlowerHand, 0xC00000FF);
queuepoly(VBODY, shSuspenders, 0xC00000FF);
}
}
@ -1149,6 +1149,24 @@ bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, dou
if(!peace::on) queuepoly(VBODY, shPSword, darkena(col, 0, 0xFF));
queuepoly(VHEAD, shArmor, darkena(col, 1, 0xFF));
}
else if(m == moNarciss) {
ShadowV(V, shPBody);
otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase);
queuepoly(VBODY, shFlowerHand, darkena(col, 0, 0xFF));
queuepoly(VBODY, shPBody, 0xFFE080FF);
if(!peace::on) queuepoly(VBODY, shPKnife, 0xC0C0C0FF);
queuepoly(VHEAD, shPFace, 0xFFE080FF);
queuepoly(VHEAD, shPHead, 0x806A00FF);
}
else if(m == moMirrorSpirit) {
ShadowV(V, shPBody);
otherbodyparts(V, darkena(col, 0, 0x90), m, footphase);
queuepoly(VBODY, shPBody, darkena(col, 0, 0x90));
if(!peace::on) queuepoly(VBODY * Mirror, shPSword, darkena(col, 0, 0xD0));
queuepoly(VHEAD, shPHead, darkena(col, 1, 0x90));
queuepoly(VHEAD, shPFace, darkena(col, 1, 0x90));
queuepoly(VHEAD, shArmor, darkena(col, 0, 0xC0));
}
else if(m == moGhost || m == moSeep || m == moFriendlyGhost) {
if(m == moFriendlyGhost) col = fghostcolor(ticks, where);
queuepoly(VGHOST, shGhost, darkena(col, 0, m == moFriendlyGhost ? 0xC0 : 0x80));
@ -1449,23 +1467,29 @@ bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) {
}
}
double chainAngle(cell *c, transmatrix& V, cell *c2, double dft) {
if(inmirrorcount || !gmatrix0.count(c2)) return dft;
double chainAngle(cell *c, transmatrix& V, cell *c2, double dft, const transmatrix &Vwhere) {
if(!gmatrix0.count(c2)) return dft;
hyperpoint h = C0;
if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h;
h = inverse(V) * gmatrix0[c2] * h;
if(inmirrorcount)
h = inverse(V) * Vwhere * inverse(gmatrix0[c]) * gmatrix0[c2] * h;
else
h = inverse(V) * gmatrix0[c2] * h;
return atan2(h[1], h[0]);
}
// equivalent to V = V * spin(-chainAngle(c,V,c2,dft));
bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, int b) {
if(inmirrorcount || !gmatrix0.count(c2)) {
bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, int b, const transmatrix &Vwhere) {
if(!gmatrix0.count(c2)) {
V = V * ddspin(c,i,b);
return false;
}
hyperpoint h = C0;
if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h;
h = inverse(V) * gmatrix0[c2] * h;
if(inmirrorcount)
h = inverse(V) * Vwhere * inverse(gmatrix0[c]) * gmatrix0[c2] * h;
else
h = inverse(V) * gmatrix0[c2] * h;
V = V * rspintox(h);
return true;
}
@ -1508,8 +1532,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
double footphaseb = 0, footphase = 0;
transmatrix Vs = Vparam; nospins = applyAnimation(c, Vs, footphase, LAYER_SMALL);
transmatrix Vb = Vparam;
if(!inmirrorcount) nospinb = applyAnimation(c, Vb, footphaseb, LAYER_BIG);
transmatrix Vb = Vparam; nospinb = applyAnimation(c, Vb, footphaseb, LAYER_BIG);
// nospin = true;
eMonster m = c->monst;
@ -1523,7 +1546,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
if(mmmon) {
if(nospinb)
chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0);
chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0, Vparam);
else
Vb = Vb * ddspin(c, c->mondir);
@ -1602,7 +1625,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
char part = dragon::bodypart(c, dragon::findhead(c));
if(part == 't') {
if(nospinb) {
chainAnimation(c, Vb, c2, nd, 0);
chainAnimation(c, Vb, c2, nd, 0, Vparam);
Vb = Vb * pispin;
}
else {
@ -1614,9 +1637,9 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
}
else if(true) {
if(nospinb) {
chainAnimation(c, Vb, c2, nd, 0);
chainAnimation(c, Vb, c2, nd, 0, Vparam);
Vb = Vb * pispin;
double ang = chainAngle(c, Vb, c->mov[c->mondir], (displaydir(c, c->mondir) - displaydir(c, nd)) * M_PI / S42);
double ang = chainAngle(c, Vb, c->mov[c->mondir], (displaydir(c, c->mondir) - displaydir(c, nd)) * M_PI / S42, Vparam);
ang /= 2;
Vb = Vb * spin(M_PI-ang);
}
@ -1642,30 +1665,40 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
}
else if(isMimic(c)) {
if(!nospins)
Vs = Vs * ddspin(c, c->mondir, flipplayer ? S42 : 0);
if(inmirrorcount&1) col ^= minf[moMirror].color ^ minf[moMirage].color;
if(c->monst == moMirror) Vs = Vs * Mirror;
int xdir = 0, copies = 1;
if(c->wall == waMirrorWall) {
xdir = mirror::mirrordir(c);
copies = 2;
if(xdir == -1) copies = 6, xdir = 0;
}
for(auto& m: mirror::mirrors) if(c == m.second.c)
for(int d=0; d<copies; d++) {
multi::cpid = m.first;
auto cw = m.second;
if(d&1) cwmirrorat(cw, xdir);
if(d>=2) cwspin(cw, 2);
if(d>=4) cwspin(cw, 2);
transmatrix Vs = Vparam;
bool mirr = cw.mirrored;
Vs = Vs * ddspin(c, cw.spin-cwt.spin, euclid ? 0 : S42);
nospins = applyAnimation(cwt.c, Vs, footphase, LAYER_SMALL);
if(!nospins) Vs = Vs * ddspin(c, cwt.spin);
if(mirr) Vs = Vs * Mirror;
if(inmirrorcount&1) mirr = !mirr;
col = mirrorcolor(geometry == gElliptic ? det(Vs) < 0 : mirr);
if(!nospins && flipplayer) Vs = Vs * pispin;
if(mmmon) {
drawMonsterType(moMimic, c, Vs, col, footphase);
drawPlayerEffects(Vs, c, false);
}
if(!mouseout() && !nospins) {
transmatrix invxy = Id;
if(flipplayer) invxy[0][0] = invxy[1][1] = -1;
multi::cpid = c->hitpoints;
if(mmmon) {
drawMonsterType(c->monst, c, Vs, col, footphase);
drawPlayerEffects(Vs, c, false);
hyperpoint P2 = Vs * inverse(cwtV) * invxy * mouseh;
queuechr(P2, 10, 'x', 0xFF00);
}
}
if(flipplayer) Vs = Vs * pispin;
if(!mouseout() && !nospins) {
// transmatrix invxy = Id; invxy[0][0] = invxy[1][1] = -1;
hyperpoint P2 = Vs * inverse(cwtV) * mouseh;
queuechr(P2, 10, 'x', 0xFF00);
}
return !mmmon;
}
@ -1707,7 +1740,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
else if(c->monst == moKrakenT) {
if(c->hitpoints == 0) col = 0x404040;
if(nospinb) {
chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0);
chainAnimation(c, Vb, c->mov[c->mondir], c->mondir, 0, Vparam);
Vb = Vb * pispin;
}
else Vb = Vb * ddspin(c, c->mondir, S42);
@ -1813,12 +1846,14 @@ void drawaura() {
for(int v=0; v<4; v++) sumaura(v);
#if CAP_SDL || CAP_GL
double bak[3];
bak[0] = ((backcolor>>16)&255)/255.;
bak[1] = ((backcolor>>8)&255)/255.;
bak[2] = ((backcolor>>0)&255)/255.;
#endif
#ifndef NOSDL
#if CAP_SDL
if(!vid.usingGL) {
SDL_LockSurface(s);
for(int y=0; y<vid.yres; y++)
@ -1858,7 +1893,7 @@ void drawaura() {
}
#endif
#ifdef GL
#if CAP_GL
setcameraangle(true);
glEnableClientState(GL_COLOR_ARRAY);
@ -2249,7 +2284,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
if(c->wall == waPlatform) wcol = 0xF0F0A0;
}
if(c->land == laWineyard) fcol = 0x006000;
if(c->land == laMirror || c->land == laMirrorWall)
if(c->land == laMirror || c->land == laMirrorWall || c->land == laMirrorOld)
fcol = 0x808080;
if(c->land == laMotion) fcol = 0xF0F000;
if(c->land == laGraveyard) fcol = 0x107010;
@ -2344,7 +2379,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
if(c->land == laCamelot) {
int d = showoff ? 0 : ((euclid||c->master->alt) ? celldistAltRelative(c) : 0);
#ifdef TOUR
#if CAP_TOUR
if(!tour::on) camelotcheat = false;
if(camelotcheat)
fcol = (d&1) ? 0xC0C0C0 : 0x606060;
@ -3115,7 +3150,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
// floor
#ifndef NOEDIT
#if CAP_EDIT
transmatrix Vpdir = V * applyPatterndir(c);
#endif
@ -3130,7 +3165,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
}
}
#ifndef NOEDIT
#if CAP_EDIT
if(mapeditor::drawUserShape(Vpdir, mapeditor::cellShapeGroup(), mapeditor::realpatternsh(c),
darkena(fcol, fd, (cmode & sm::DRAW) ? 0xC0 : 0xFF), c));
@ -3171,27 +3206,37 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
if(c->mov[d] && c->mov[(1+d)%6] && c->mov[d]->land == laMirrorWall && c->mov[(1+d)%6]->land == laMirrorWall)
break;
qfi.spin = ddspin(c, d, 0);
transmatrix V2 = V * qfi.spin;
for(int d=0; d<6; d++) {
transmatrix V2 = V * qfi.spin;
if(!wmblack) for(int d=0; d<6; d++) {
inmirrorcount+=d;
qfloor(c, V2 * spin(d*M_PI/3), shHalfFloor[2], darkena(fcol, fd, 0xFF));
inmirrorcount-=d;
}
if(wmspatial) {
const int layers = 2 << detaillevel;
for(int z=1; z<layers; z++)
queuepolyat(mscale(V2, zgrad0(0, geom3::wall_height, z, layers)), shHalfMirror[2], 0xC0C0C080, PPR_WALL3+z-layers);
}
const int layers = 2 << detaillevel;
for(int z=1; z<layers; z++)
queuepolyat(mscale(V2, zgrad0(0, geom3::wall_height, z, layers)), shHalfMirror[2], 0xC0C0C080, PPR_WALL3+z-layers);
else
queuepolyat(V2, shHalfMirror[2], 0xC0C0C080, PPR_WALL3);
}
else {
qfi.spin = ddspin(c, d, S42);
transmatrix V2 = V * qfi.spin;
inmirrorcount++;
qfloor(c, mirrorif(V2, !onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF));
inmirrorcount--;
qfloor(c, mirrorif(V2, onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF));
if(!wmblack) {
inmirrorcount++;
qfloor(c, mirrorif(V2, !onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF));
inmirrorcount--;
qfloor(c, mirrorif(V2, onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF));
}
const int layers = 2 << detaillevel;
for(int z=1; z<layers; z++)
queuepolyat(mscale(V2, zgrad0(0, geom3::wall_height, z, layers)), shHalfMirror[ct6], 0xC0C0C080, PPR_WALL3+z-layers);
if(wmspatial) {
const int layers = 2 << detaillevel;
for(int z=1; z<layers; z++)
queuepolyat(mscale(V2, zgrad0(0, geom3::wall_height, z, layers)), shHalfMirror[ct6], 0xC0C0C080, PPR_WALL3+z-layers);
}
else
queuepolyat(V2, shHalfMirror[ct6], 0xC0C0C080, PPR_WALL3);
}
}
@ -3464,7 +3509,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
}
// walls
#ifndef NOEDIT
#if CAP_EDIT
if(mapeditor::displaycodes) {
@ -3904,7 +3949,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
applyAnimation(c, Vboat0, footphase, LAYER_BOAT);
}
#ifndef NOEDIT
#if CAP_EDIT
if(c == mapeditor::drawcell && mapeditor::drawcellShapeGroup() == 2)
mapeditor::drawtrans = V;
#endif
@ -4080,15 +4125,13 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
if(!inHighQual) {
#ifndef NOEDIT
#if CAP_EDIT
if((cmode & sm::MAP) && lmouseover && darken == 0 &&
!mouseout() &&
(mapeditor::whichPattern ? mapeditor::subpattern(c) == mapeditor::subpattern(lmouseover) : c == lmouseover)) {
queuecircle(V, .78, 0x00FFFFFF);
}
#endif
#ifndef NOEDIT
mapeditor::drawGhosts(c, V, ct);
#endif
}
@ -4100,7 +4143,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
queueline(tC0(V), V*tC0(hexmove[c->bardir]), col, 2);
}
#ifndef NOMODEL
#if CAP_MODEL
netgen::buildVertexInfo(c, V);
#endif
}
@ -4175,7 +4218,7 @@ void queuecircleat(cell *c, double rad, int col) {
#define Gm(x) gmatrix[x]
#define Gm0(x) tC0(gmatrix[x])
#ifdef MOBILE
#if ISMOBILE==1
#define MOBON (clicked)
#else
#define MOBON true
@ -4187,11 +4230,7 @@ void drawMarkers() {
if(!inHighQual) {
#ifdef PANDORA
bool ok = mousepressed;
#else
bool ok = true;
#endif
bool ok = !ISPANDORA || mousepressed;
if(G(dragon::target) && haveMount()) {
queuechr(Gm0(dragon::target), 2*vid.fsize, 'X',
@ -4223,15 +4262,19 @@ void drawMarkers() {
queuecircleat(global_pushto, .6, darkena(0xFFD500, 0, 0xFF));
}
#if CAP_JOY
if(joydir.d >= 0)
queuecircleat(cwt.c->mov[(joydir.d+cwt.spin) % cwt.c->type], .78 - .02 * sin(ticks/199.0),
darkena(0x00FF00, 0, 0xFF));
#endif
#ifndef NOMODEL
if(centerover && !playermoved && netgen::mode == 0 && !conformal::on)
bool m = true;
#if CAP_MODEL
m = netgen::mode == 0;
#endif
if(centerover && !playermoved && m && !conformal::on)
queuecircleat(centerover, .70 - .06 * sin(ticks/200.0),
darkena(int(175 + 25 * sin(ticks / 200.0)), 0, 0xFF));
#endif
if(multi::players > 1 || multi::alwaysuse) for(int i=0; i<numplayers(); i++) {
multi::cpid = i;
@ -4242,7 +4285,7 @@ void drawMarkers() {
// process mouse
#ifdef MOBILE
#if ISMOBILE
extern bool useRangedOrb;
if(canmove && !shmup::on && andmode == 0 && !useRangedOrb && vid.mobilecompasssize > 0) {
using namespace shmupballs;
@ -4424,7 +4467,7 @@ void drawthemap() {
multi::ccdist[i] = 1e20; multi::ccat[i] = NULL;
}
#ifdef MOBILE
#if ISMOBILE
mouseovers = XLAT("No info about this...");
#endif
if(mouseout())
@ -4491,7 +4534,7 @@ void drawthemap() {
}
}
#ifndef NOSDL
#if CAP_SDL
Uint8 *keystate = SDL_GetKeyState(NULL);
lmouseover = mouseover;
bool useRangedOrb = (!(vid.shifttarget & 1) && haveRangedOrb() && lmouseover && lmouseover->cpdist > 1) || (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]);
@ -4506,7 +4549,7 @@ void drawthemap() {
movepcto(mousedest.d, mousedest.subdir, true);
for(int i=0; i<ittypes; i++) orbused[i] = recorduse[i];
items[itWarning] -= 2;
if(multi::players == 1 && cw.spin != cwt.spin) mirror::spin(-mousedest.d);
if(cw.spin != cwt.spin) mirror::act(-mousedest.d, mirror::SPINSINGLE);
cwt = cw; flipplayer = f;
lmouseover = mousedest.d >= 0 ? cwt.c->mov[(cwt.spin + mousedest.d) % cwt.c->type] : cwt.c;
}
@ -4522,7 +4565,7 @@ void drawmovestar(double dx, double dy) {
if(!playerfound) return;
if(shmup::on) return;
#ifndef NORUG
#if CAP_RUG
if(rug::rugged && multi::players == 1 && !multi::alwaysuse) return;
#endif
@ -4549,7 +4592,7 @@ void drawmovestar(double dx, double dy) {
else for(int d=0; d<8; d++) {
int col = starcol;
#ifdef PANDORA
#if ISPANDORA
if(leftclick && (d == 2 || d == 6 || d == 1 || d == 7)) col &= 0xFFFFFF3F;
if(rightclick && (d == 2 || d == 6 || d == 3 || d == 5)) col &= 0xFFFFFF3F;
if(!leftclick && !rightclick && (d&1)) col &= 0xFFFFFF3F;
@ -4591,7 +4634,7 @@ void calcparam() {
else {
if(vid.xres >= vid.yres * 5/4-16 && (cmode & sm::SIDE))
sidescreen = true;
#ifdef TOUR
#if CAP_TOUR
if(tour::on && (tour::slides[tour::currentslide].flags & tour::SIDESCREEN))
sidescreen = true;
#endif
@ -4655,7 +4698,6 @@ void drawfullmap() {
clearaura();
drawthemap();
#ifndef NORUG
if(!inHighQual) {
if((cmode & sm::NORMAL) && !rug::rugged) {
if(multi::players > 1) {
@ -4669,10 +4711,13 @@ void drawfullmap() {
else
drawmovestar(0, 0);
}
#if CAP_RUG
if(rug::rugged && !rug::renderonce) queueline(C0, mouseh, 0xFF00FFFF, 5);
#endif
#if CAP_EDIT
if(cmode & sm::DRAW) mapeditor::drawGrid();
#endif
}
#endif
profile_start(2);
drawaura();
@ -4680,27 +4725,31 @@ void drawfullmap() {
profile_stop(2);
}
#ifdef ISMOBILE
int andmode;
#endif
void gamescreen(int _darken) {
darken = _darken;
if(conformal::includeHistory) conformal::restore();
#ifndef NORUG
#if CAP_RUG
if(rug::rugged) {
rug::actDraw();
}
} else
#endif
else drawfullmap();
drawfullmap();
if(conformal::includeHistory) conformal::restoreBack();
poly_outline = OUTLINE_DEFAULT;
#ifdef MOBILE
#if ISMOBILE
buttonclicked = false;
if(cmode == smNormal) {
if(cmode & sm::NORMAL) {
if(andmode == 0 && shmup::on) {
using namespace shmupballs;
calc();
@ -4725,12 +4774,12 @@ void gamescreen(int _darken) {
void normalscreen() {
help = "@";
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(!rogueviz::on)
#endif
mouseovers = XLAT("Press F1 or right click for help");
#ifdef TOUR
#if CAP_TOUR
if(tour::on) mouseovers = tour::tourhelp;
#endif
@ -4740,7 +4789,7 @@ void normalscreen() {
gamescreen(hiliteclick && mmmon ? 1 : 0); drawStats();
if(nomenukey)
;
#ifdef TOUR
#if CAP_TOUR
else if(tour::on)
displayButton(vid.xres-8, vid.yres-vid.fsize, XLAT("(ESC) tour menu"), SDLK_ESCAPE, 16);
else
@ -4762,20 +4811,24 @@ void drawscreen() {
DEBB(DF_GRAPH, (debugfile,"drawscreen\n"));
calcparam();
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::fixparam();
#endif
#ifdef GL
#if CAP_GL
if(vid.usingGL) setGLProjection();
#endif
#ifndef NOSDL
#if CAP_SDL
// SDL_LockSurface(s);
// unsigned char *b = (unsigned char*) s->pixels;
// int n = vid.xres * vid.yres * 4;
// while(n) *b >>= 1, b++, n--;
// memset(s->pixels, 0, vid.xres * vid.yres * 4);
if(!vid.usingGL) SDL_FillRect(s, NULL, backcolor);
#if CAP_GL
if(!vid.usingGL)
#endif
SDL_FillRect(s, NULL, backcolor);
#endif
// displaynum(vx,100, 0, 24, 0xc0c0c0, celldist(cwt.c), ":");
@ -4787,12 +4840,12 @@ void drawscreen() {
cmode = 0;
keyhandler = [] (int sym, int uni) { return false; };
if(!size(screens)) pushScreen(normalscreen);
screens.back()();
#if !ISMOBILE
int col = linf[cwt.c->land].color;
if(cwt.c->land == laRedRock) col = 0xC00000;
#ifndef MOBILE
displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, mouseovers, col, 8);
#endif
@ -4844,8 +4897,8 @@ void drawscreen() {
// SDL_UnlockSurface(s);
DEBT("swapbuffers");
#ifndef NOSDL
#ifdef GL
#if CAP_SDL
#if CAP_GL
if(vid.usingGL) SDL_GL_SwapBuffers(); else
#endif
SDL_UpdateRect(s, 0, 0, vid.xres, vid.yres);
@ -4882,7 +4935,7 @@ auto graphcm = addHook(clearmemory, 0, [] () {
void resetGeometry() {
precalc();
fp43.analyze();
#ifdef GL
#if CAP_GL
resetGL();
#endif
}

View File

@ -1,22 +1,20 @@
string help;
#ifndef NOLAMBDAS
function<void()> help_delegate;
#endif
string buildHelpText() {
DEBB(DF_GRAPH, (debugfile,"buildHelpText\n"));
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(rogueviz::on) return rogueviz::makehelp();
#endif
string h;
h += XLAT("Welcome to HyperRogue");
#ifdef ANDROID
#if ISANDROID
h += XLAT(" for Android");
#endif
#ifdef IOS
#if ISIOS
h += XLAT(" for iOS");
#endif
h += XLAT("! (version %1)\n\n", VER);
@ -54,7 +52,7 @@ string buildHelpText() {
"get the details of all the Lands.\n\n");
h += "\n\n";
#ifdef MOBILE
#if ISMOBILE
h += XLAT(
"Usually, you move by touching somewhere on the map; you can also touch one "
"of the four buttons on the map corners to change this (to scroll the map "
@ -69,14 +67,14 @@ string buildHelpText() {
h += XLAT(
"You can right click any element to get more information about it.\n\n"
);
#ifdef MAC
#if ISMAC
h += XLAT("(You can also use right Shift)\n\n");
#endif
#endif
h += XLAT("See more on the website: ")
+ "http//roguetemple.com/z/hyper/\n\n";
#ifdef TOUR
#if CAP_TOUR
h += XLAT("Try the Tutorial to help with understanding the "
"geometry of HyperRogue (menu -> special modes).\n\n");
#endif
@ -100,12 +98,13 @@ string buildCredits() {
h += XLAT(
"special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n",
"Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct, "
"wonderfullizardofoz, Piotr MigdaĹ, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman"
"wonderfullizardofoz, Piotr MigdaĹ, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman, "
"Kojiguchi Kazuki, baconcow"
);
#ifdef EXTRALICENSE
h += EXTRALICENSE;
#endif
#ifndef MOBILE
#if !ISMOBILE
h += XLAT(
"\n\nSee sounds/credits.txt for credits for sound effects"
);
@ -118,7 +117,7 @@ string pushtext(stringpar p) {
string s = XLAT(
"\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction "
"by clicking left or right half of the heptagon.", p);
#ifndef MOBILE
#if !ISMOBILE
s += XLAT(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down).");
#endif
return s;
@ -184,7 +183,7 @@ string generateHelpForItem(eItem it) {
" You need to go deep to collect lots of them.");
}
#ifdef MOBILE
#if ISMOBILE==1
if(it == itOrbSafety)
help += XLAT("This might be very useful for devices with limited memory.");
#else
@ -194,22 +193,22 @@ string generateHelpForItem(eItem it) {
if(isRangedOrb(it)) {
help += XLAT("\nThis is a ranged Orb. ");
#ifdef ISMOBILE
#if ISMOBILE
if(vid.shifttarget&2)
help += XLAT("\nRanged Orbs can be targeted by long touching the desired location.");
else
help += XLAT("\nRanged Orbs can be targeted by touching the desired location.");
#else
if(vid.shifttarget&1)
help += XLAT("\nRanged Orbs can be targeted by shift-clicking the desired location. "
help += XLAT("\nRanged Orbs can be targeted by shift-clicking the desired location. ");
else
help += XLAT("\nRanged Orbs can be targeted by clicking the desired location. ");
help += "You can also scroll to the desired location and then press 't'.");
help += XLAT("You can also scroll to the desired location and then press 't'.");
#endif
help += XLAT("\nYou can never target cells which are adjacent to the player character, or ones out of the sight range.");
}
#ifdef MOBILE
#if ISMOBILE
if(it == itGreenStone)
help += XLAT("You can touch the Dead Orb in your inventory to drop it.");
#else
@ -314,7 +313,7 @@ void addMinefieldExplanation(string& s) {
);
s += "\n\n";
#ifdef MOBILE
#if ISMOBILE==1
s += XLAT("Known mines may be marked by pressing 'm'. Your allies won't step on marked mines.");
#else
s += XLAT("Known mines may be marked by touching while in drag mode. Your allies won't step on marked mines.");
@ -345,7 +344,7 @@ string generateHelpForMonster(eMonster m) {
string s = helptitle(XLATN(minf[m].name), minf[m].color);
if(m == moPlayer) {
#ifdef TOUR
#if CAP_TOUR
if(tour::on)
return s+XLAT(
"A tourist from another world. They mutter something about the 'tutorial', "
@ -569,7 +568,7 @@ string generateHelpForLand(eLand l) {
);
}
#ifndef ISMOBILE
#if !ISMOBILE
if(l == laCA)
s += XLAT("\n\nHint: use 'm' to toggle cells quickly");
#endif
@ -701,7 +700,7 @@ void describeMouseover() {
help += s0 + "\n\n" + warpdesc;
}
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::describe(c);
#endif

12
hud.cpp
View File

@ -112,10 +112,10 @@ int glyphflags(int gid) {
if(i == treasureType(cwt.c->land))
f |= GLYPH_LOCAL | GLYPH_LOCAL2 | GLYPH_IMPORTANT | GLYPH_INSQUARE;
if(i == itHolyGrail) {
if(items[i] >= 3) f |= GLYPH_MARKOVER;
if(items[i] >= 3 && !inv::on) f |= GLYPH_MARKOVER;
}
else if(itemclass(i) == IC_TREASURE) {
if(items[i] >= 25 && items[i] < 100) f |= GLYPH_MARKOVER;
if(items[i] >= 25 && items[i] < 100 && !inv::on) f |= GLYPH_MARKOVER;
else if(items[i] < 10) f |= GLYPH_MARKTODO;
}
else {
@ -152,7 +152,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, int color, int qty
initquickqueue();
if(id >= ittypes) {
eMonster m = eMonster(id - ittypes);
int bsize = buttonsize;
int bsize = buttonsize * 2/3;
if(m == moKrakenH) bsize /= 3;
if(m == moKrakenT || m == moDragonTail) bsize /= 2;
if(m == moSlime) bsize = (2*bsize+1)/3;
@ -163,7 +163,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, int color, int qty
}
else {
eItem it = eItem(id);
int bsize = buttonsize;
int bsize = buttonsize / 2;
if(glyph =='*') bsize *= 2;
if(glyph == '$') bsize = (bsize*5+2)/3;
if(glyph == 'o') bsize = (bsize*3+1)/2;
@ -265,7 +265,7 @@ hookset<bool()> *hooks_prestats;
void drawStats() {
callhandlers(false, hooks_prestats);
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(rogueviz::on || nohud) return;
#endif
if(viewdists && sidescreen) {
@ -446,7 +446,7 @@ void drawStats() {
"If you find that animations are not smooth enough, you can try "
"to change the options "
) +
#ifdef IOS
#if ISIOS
XLAT(
"(in the MENU). You can reduce the sight range, this should make "
"the animations smoother.");

View File

@ -15,19 +15,25 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define ISANDROID 0
#define ISMOBILE 0
#define ISIOS 0
#define USE_SDL
#define USE_COMMANDLINE
#ifdef MAC
#define ISMAC 1
#endif
#ifdef STEAM
#ifdef LINUX
#define ISLINUX 1
#endif
#ifdef WINDOWS
#define ISWINDOWS 1
#endif
#if ISSTEAM
#define NOLICENSE
#endif
#include "init.cpp"
#ifdef LINUX
#if ISLINUX
#include <sys/resource.h>
void moreStack() {
@ -102,10 +108,10 @@ int arg::readCommon() {
if(argis("-c")) { PHASE(1); shift(); conffile = args(); }
else if(argis("-s")) { PHASE(1); shift(); scorefile = args(); }
else if(argis("-m")) { PHASE(1); shift(); musicfile = args(); }
#ifdef SDLAUDIO
#if CAP_SDLAUDIO
else if(argis("-se")) { PHASE(1); shift(); wheresounds = args(); }
#endif
#ifndef NOEDIT
#if CAP_EDIT
else if(argis("-lev")) { shift(); levelfile = args(); }
else if(argis("-pic")) { shift(); picfile = args(); }
else if(argis("-load")) { PHASE(3); shift(); mapstream::loadMap(loadlevel); }
@ -287,7 +293,7 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
else if(argis("--run")) {
PHASE(3); mainloop(); quitmainloop = false;
}
#ifdef TOUR
#if CAP_TOUR
else if(argis("--tour")) {
PHASE(3); tour::start();
}
@ -315,7 +321,7 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
PHASEFROM(2);
shift(); sightrange = argi();
}
#ifndef NOSDL
#if CAP_SDL
else if(argis("-pngshot")) {
PHASE(3); shift();
printf("saving PNG screenshot to %s\n", args());
@ -330,14 +336,12 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
// note: use '-svgfont latex' to produce text output as: \myfont{size}{text}
// (this is helpful with Inkscape's PDF+TeX output feature; define \myfont yourself)
}
#ifndef NOPNG
else if(argis("-pngsize")) {
shift(); sscanf(args(), "%d", &pngres);
}
else if(argis("-pngformat")) {
shift(); sscanf(args(), "%d", &pngformat);
}
#endif
else if(argis("-svggamma")) {
shift(); svg::gamma = argf();
}
@ -400,8 +404,8 @@ hookset<bool(int argc, char** argv)> *hooks_main;
#ifndef NOMAIN
int main(int argc, char **argv) {
if(callhandlers(false, hooks_main, argc, argv)) return 0;
#ifndef WEB
#ifdef LINUX
#if !ISWEB
#if ISLINUX
moreStack();
#endif
arg::init(argc, argv);
@ -416,7 +420,7 @@ int main(int argc, char **argv) {
}
#endif
#ifdef USE_COMMANDLINE
#if CAP_COMMANDLINE
purehookset hooks_config;
hookset<int()> *hooks_args;

94
hyper.h
View File

@ -112,8 +112,12 @@ namespace hive { void createBugArmy(cell *c); }
namespace whirlpool { void generate(cell *wto); }
namespace whirlwind { void generate(cell *wto); }
namespace mirror {
void createMirrors(cell *c, int dir, eMonster type);
void createMirages(cell *c, int dir, eMonster type);
static const int SPINSINGLE = 1;
static const int SPINMULTI = 2;
static const int GO = 4;
static const int ATTACK = 8;
void act(int dir, int flags);
}
int neighborId(cell *c1, cell *c2);
@ -276,13 +280,13 @@ bool displaystr(int x, int y, int shift, int size, const string& str, int color,
extern int darken, inmirrorcount;
void calcparam();
#ifdef USE_SDL
#if CAP_SDL
int& qpixel(SDL_Surface *surf, int x, int y);
void setvideomode();
void saveHighQualityShot(const char *fname = NULL, const char *caption = NULL, int fade = 255);
#endif
#ifndef NOCONFIG
#if CAP_CONFIG
void saveConfig();
#endif
@ -391,7 +395,7 @@ namespace mapeditor {
void showDrawEditor();
}
#ifndef NORUG
#if CAP_RUG
namespace rug {
extern bool rugged;
extern bool renderonce;
@ -451,13 +455,6 @@ void selectEyeMask(int ed);
extern int ticks;
void setGLProjection();
#ifdef LOCAL
extern void process_local_stats();
bool localDescribe();
void localDrawMap();
extern bool localKill(shmup::monster *m);
#endif
// passable flags
#define P_MONSTER (1<<0) // can move through monsters
@ -529,14 +526,13 @@ extern bool safety;
#define INF 9999
#define INFD 20
#define PINFD 125
#define BARLEV ((ISANDROID||ISIOS||purehepta)?9:10)
#define BARLEV ((ISANDROID||ISIOS||ISFAKEMOBILE||purehepta)?9:10)
#define BUGLEV 15
// #define BARLEV 9
bool isKillable(cell *c);
bool isKillableSomehow(cell *c);
extern vector<cell*> mirrors, mirrors2;
bool isAlchAny(eWall w);
bool isAlchAny(cell *c);
@ -689,16 +685,17 @@ int getGhostcount();
void raiseBuggyGeneration(cell *c, const char *s);
void verifyMutantAround(cell *c);
// #define NOPNG
#if CAP_SDL
#ifdef NOPNG
#define IMAGEEXT ".bmp"
#define IMAGESAVE SDL_SaveBMP
#else
#if CAP_PNG
#include "savepng.h"
#define IMAGEEXT ".png"
void IMAGESAVE(SDL_Surface *s, const char *fname);
#else
#define IMAGEEXT ".bmp"
#define IMAGESAVE SDL_SaveBMP
#endif
#endif
void drawscreen();
@ -715,7 +712,7 @@ bool isDragon(eMonster m);
// for some reason I need this to compile under OSX
#ifdef MAC
#if ISMAC
extern "C" { void *_Unwind_Resume = 0; }
#endif
@ -790,15 +787,9 @@ bool againstCurrent(cell *w, cell *from);
extern bool timerghost;
#ifdef PANDORA
#define MENU_SCALING
#endif
#define CAP_MENUSCALING (ISPANDORA || ISMOBILE)
#ifdef MOBILE
#define MENU_SCALING
#endif
#ifdef MENU_SCALING
#if CAP_MENUSCALING
#define displayfrZ dialog::displayzoom
#else
#define displayfrZ displayfr
@ -952,7 +943,8 @@ enum PPR {
PPR_ONTENTACLE, PPR_ONTENTACLE_EYES, PPR_ONTENTACLE_EYES2,
PPR_MONSTER_SHADOW,
PPR_MONSTER_FOOT, PPR_MONSTER_LEG, PPR_MONSTER_GROIN,
PPR_MONSTER_BODY, PPR_MONSTER_SUBWPN, PPR_MONSTER_WPN, PPR_MONSTER_ARMOR0, PPR_MONSTER_ARMOR1,
PPR_MONSTER_SUBWPN, PPR_MONSTER_WPN,
PPR_MONSTER_BODY, PPR_MONSTER_ARMOR0, PPR_MONSTER_ARMOR1,
PPR_MONSTER_CLOAK, PPR_MONSTER_NECK,
PPR_MONSTER_HEAD, PPR_MONSTER_FACE, PPR_MONSTER_EYE0, PPR_MONSTER_EYE1,
PPR_MONSTER_HAIR, PPR_MONSTER_HAT0, PPR_MONSTER_HAT1,
@ -1013,7 +1005,7 @@ enum eGlyphsortorder {
extern eGlyphsortorder glyphsortorder;
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
namespace rogueviz {
extern bool on;
string describe(shmup::monster *m);
@ -1102,7 +1094,7 @@ extern int cshpos;
namespace arg {
#ifdef USE_COMMANDLINE
#if CAP_COMMANDLINE
extern int argc; extern char **argv;
inline void lshift() {
@ -1150,13 +1142,7 @@ void verifycells(heptagon *at);
int zebra40(cell *c);
cell *createMov(cell *c, int d);
#ifndef MOBWEB
#ifndef TOUR
#define TOUR
#endif
#endif
#ifdef TOUR
#if CAP_TOUR
namespace tour {
extern bool on;
extern string tourhelp;
@ -1214,9 +1200,11 @@ namespace tour {
namespace rogueviz {
extern bool rog3;
extern bool rvwarp;
#if CAP_TOUR
namespace rvtour {
extern tour::slide rvslides[];
}
#endif
};
extern bool doCross;
@ -1243,6 +1231,7 @@ namespace sm {
static const int DOTOUR = 512;
static const int CENTER = 1024;
static const int A3 = 2048; // affects poly
static const int ZOOMABLE = 4096;
};
namespace linepatterns {
@ -1397,7 +1386,7 @@ int textwidth(int siz, const string &str);
extern bool gtouched, mousepressed, mousemoved, actonrelease;
extern bool inslider;
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
#define DOSHMUP (shmup::on || rogueviz::on)
#else
#define DOSHMUP shmup::on
@ -1422,10 +1411,10 @@ void loadConfig();
extern bool auraNOGL;
#ifndef NOSDL
#if CAP_SDLJOY
extern void initJoysticks();
extern int joyx, joyy, panjoyx, panjoyy;
extern bool autojoy;
extern int joyx, joyy, panjoyx, panjoyy;
extern movedir joydir;
extern SDL_Joystick* sticks[8];
extern int numsticks;
@ -1434,7 +1423,7 @@ void closeJoysticks();
void preparesort();
#ifdef MOBILE
#if ISMOBILE==1
#define SHMUPTITLE "shoot'em up mode"
#else
#define SHMUPTITLE "shoot'em up and multiplayer"
@ -1472,7 +1461,7 @@ void showMission();
void handleKeyQuit(int sym, int uni);
void handlePanning(int sym, int uni);
#ifdef MOBILE
#if ISMOBILE==1
namespace leader { void showMenu(); void handleKey(int sym, int uni); }
#endif
@ -1497,12 +1486,6 @@ extern int hinttoshow;
bool isShmupLifeOrb(eItem it);
int orbcharges(eItem it);
#ifdef PANDORA
static const bool ISPANDORA = true;
#else
static const bool ISPANDORA = false;
#endif
int gradient(int c0, int c1, ld v0, ld v, ld v1);
struct hint {
@ -1514,3 +1497,14 @@ struct hint {
extern hint hints[];
int counthints();
void gainShard(cell *c2, const char *msg);
int textwidth(int siz, const string &str);
#if CAP_GL
int gl_width(int size, const char *s);
#endif
#ifdef ISMOBILE
extern int andmode;
#endif

View File

@ -166,6 +166,9 @@ const transmatrix Id = {{{1,0,0}, {0,1,0}, {0,0,1}}};
// mirror image
const transmatrix Mirror = {{{1,0,0}, {0,-1,0}, {0,0,1}}};
// mirror image
const transmatrix MirrorX = {{{-1,0,0}, {0,1,0}, {0,0,1}}};
// rotate by PI
const transmatrix pispin = {{{-1,0,0}, {0,-1,0}, {0,0,1}}};
@ -368,20 +371,25 @@ void display(const transmatrix& T) {
printf("\n\n");
}
transmatrix inverse(transmatrix T) {
profile_start(7);
ld det(const transmatrix& T) {
ld det = 0;
for(int i=0; i<3; i++)
det += T[0][i] * T[1][(i+1)%3] * T[2][(i+2)%3];
for(int i=0; i<3; i++)
det -= T[0][i] * T[1][(i+2)%3] * T[2][(i+1)%3];
return det;
}
transmatrix inverse(const transmatrix& T) {
profile_start(7);
ld d = det(T);
transmatrix T2;
if(det == 0) return T2;
if(d == 0) return T2;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
T2[j][i] = (T[(i+1)%3][(j+1)%3] * T[(i+2)%3][(j+2)%3] - T[(i+1)%3][(j+2)%3] * T[(i+2)%3][(j+1)%3]) / det;
T2[j][i] = (T[(i+1)%3][(j+1)%3] * T[(i+2)%3][(j+2)%3] - T[(i+1)%3][(j+2)%3] * T[(i+2)%3][(j+1)%3]) / d;
profile_stop(7);
return T2;

View File

@ -1,12 +1,11 @@
#define WEB
#define MOBWEB
#define ISWEB 1
#define MINI
#define NOAUDIO
#define NOGFX
#define NOPNG
#define DEMO
#define TOUR
#define NOTTF
#define CAP_SDLTTF 0
#ifdef FAKEWEB
void mainloopiter();

360
init.cpp
View File

@ -1,73 +1,167 @@
#define VER "10.0"
#define VERNUM 10000
#define VERNUM_HEX 0xA000
#define VER "10.0c"
#define VERNUM 10003
#define VERNUM_HEX 0xA003
#define GEN_M 0
#define GEN_F 1
#define GEN_N 2
#define GEN_O 3
#ifdef MOBILE
#define MOBWEB
// OS settings
#ifndef ISMAC
#define ISMAC 0
#endif
#ifndef ISLINUX
#define ISLINUX 0
#endif
#ifndef ISWINDOWS
#define ISWINDOWS 0
#endif
#ifndef ISPANDORA
#define ISPANDORA 0
#endif
#ifndef ISIOS
#define ISIOS 0
#endif
#ifndef ISANDROID
#define ISANDROID 0
#endif
#ifndef ISWEB
#define ISWEB 0
#endif
#ifndef ISFAKEMOBILE
#define ISFAKEMOBILE 0
#endif
#define ISMOBILE (ISIOS || ISANDROID || ISFAKEMOBILE)
#define ISMOBWEB (ISMOBILE || ISWEB)
#ifndef ISMINI
#define ISMINI 0
#endif
#ifndef CAP_XGD
#define CAP_XGD (ISANDROID || ISFAKEMOBILE)
#endif
#define CAP_FRAMELIMIT (!ISMOBWEB)
#if ISMOBILE==1
#define EXTERNALFONT
#endif
#ifdef WEB
#define MOBWEB
#define ONEGRAPH
#ifndef CAP_INV
#define CAP_INV 1
#endif
#ifdef IOS
#define ONEGRAPH
#ifndef CAP_ANDROIDSHARE
#define CAP_ANDROIDSHARE (ISANDROID)
#endif
#ifdef MOBWEB
#define NORUG
#define NOEDIT
#define NOMODEL
#ifndef CAP_SDL
#define CAP_SDL (!ISMOBILE)
#endif
#ifdef MINI
#define NORUG
#define NOEDIT
#define NOMODEL
#define NOSAVE
#define NOCONFIG
#define NOTRANS
#ifndef CAP_SDLGFX
#define CAP_SDLGFX (CAP_SDL && !ISWEB)
#endif
#ifndef STEAM
#define GFX
#ifndef CAP_GL
#define CAP_GL (ISMOBILE || CAP_SDL)
#endif
#ifndef NOGL
#define GL
#ifndef CAP_AUDIO
#define CAP_AUDIO ((ISMOBILE || CAP_SDL) && !ISWEB && !ISMINI)
#endif
#define CAP_GLORNOT (CAP_GL && !ISWEB && !ISIOS)
#ifndef CAP_CERTIFY
#define CAP_CERTIFY 0
#endif
#ifndef CAP_RUG
#define CAP_RUG (!ISMOBWEB && !ISMINI && CAP_SDL && CAP_GL)
#endif
#ifndef CAP_EDIT
#define CAP_EDIT (!ISMOBWEB && !ISMINI)
#endif
#ifndef CAP_MODEL
#define CAP_MODEL (!ISMOBWEB && !ISMINI && CAP_SDLGFX)
#endif
#ifndef CAP_SAVE
#define CAP_SAVE (!ISWEB && !ISMINI)
#endif
#ifndef CAP_CONFIG
#define CAP_CONFIG (!ISWEB && !ISMINI)
#endif
#ifndef CAP_TRANS
#define CAP_TRANS (!ISWEB && !ISMINI)
#endif
#ifndef CAP_TOUR
#define CAP_TOUR (!ISWEB && !ISMINI)
#endif
#ifndef CAP_ROGUEVIZ
#define CAP_ROGUEVIZ 0
#endif
#ifndef CAP_PROFILING
#define CAP_PROFILING 0
#endif
#define PSEUDOKEY_WHEELDOWN 2501
#define PSEUDOKEY_WHEELUP 2502
#ifdef NOGFX
#undef GFX
#ifndef CAP_PNG
#define CAP_PNG (!ISMOBWEB && !ISMAC && CAP_SDLGFX)
#endif
#ifdef MAC
#define NOPNG
#ifndef CAP_COMMANDLINE
#define CAP_COMMANDLINE (!ISMOBILE)
#endif
// #define INV
#define CAP_SDLAUDIO (CAP_SDL && CAP_AUDIO)
#ifndef MOBILE
#ifndef NOAUDIO
#define SDLAUDIO
#endif
#ifndef CAP_SVG
#define CAP_SVG (!ISMOBILE)
#endif
#ifdef MOBILE
#define NOTTF
#ifndef CAP_SDLJOY
#define CAP_SDLJOY (CAP_SDL && !ISWEB)
#endif
#ifdef MOBILE
#define CAP_SDLTTF (CAP_SDL && !ISMOBILE && !ISWEB)
#define CAP_GLFONT (CAP_GL && !ISMOBILE)
#ifndef CAP_TABFONT
#define CAP_TABFONT (ISWEB)
#endif
#ifndef CAP_FIXEDSIZE
#define CAP_FIXEDSIZE (CAP_CREATEFONT || CAP_TABLEFONT ? 36 : 0)
#endif
#ifndef CAP_SHMUP
#define CAP_SHMUP 1
#endif
#if ISMOBILE
#define EXTRALICENSE "\n\nHyperRogue soundtrack by Shawn Parrotte (http://www.shawnparrotte.com), under the Creative Commons BY-SA 3.0 license, http://creativecommons.org/licenses/by-sa/3.0/"
#undef XEXTRALICENSE
@ -82,31 +176,26 @@ void gdpush(int t);
#include <stdio.h>
#ifdef NOSDL
#undef USE_SDL
#endif
#ifdef USE_SDL
#if CAP_SDL
#include <SDL/SDL.h>
#ifndef MAC
#if !ISMAC
#undef main
#endif
#ifdef SDLAUDIO
#if CAP_SDLAUDIO
#include <SDL/SDL_mixer.h>
#endif
#ifndef NOTTF
#if CAP_SDLTTF
#include <SDL/SDL_ttf.h>
#endif
#ifdef GFX
#define SDLGFX
#if CAP_SDLGFX
#include <SDL/SDL_gfxPrimitives.h>
#endif
#else
#elif !ISFAKEMOBILE
#define SDLK_F1 (123001)
#define SDLK_F2 (123002)
#define SDLK_F3 (123003)
@ -143,64 +232,36 @@ void gdpush(int t);
#define SDLK_DELETE (123052)
#define SDLK_KP_ENTER (123054)
#define SDLK_BACKSPACE (123055)
#ifndef FAKEMOBILE
typedef int SDL_Event;
#endif
#define NOSDL
#define NOTTF
#define NOPNG
#undef GFX
#define NOMODEL
#define NORUG
#define NOEDIT
#define NOAUDIO
#undef SDLAUDIO
#ifndef CAP_GLEW
#define CAP_GLEW (CAP_GL && !ISMOBILE && !ISMAC && !ISLINUX)
#endif
#ifdef GL
#ifdef MAC
#define AVOID_GLEW
#endif
#ifndef AVOID_GLEW
#if CAP_GLEW
#include <GL/glew.h>
#else
#define GL_GLEXT_PROTOTYPES 1
#ifndef MOBILE
#ifdef MAC
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#ifdef MAC
#include <OpenGL/glext.h>
#else
#include <GL/glext.h>
#endif
#endif
#ifdef ANDROID
#ifndef FAKE
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLES2/gl2.h>
#endif
#if ISMAC
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#elif ISIOS
// already included
#elif ISANDROID
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLES2/gl2.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
#endif
#endif
#ifdef NOLAMBDAS
#undef TOUR
#else
#include <functional>
#include <memory>
#endif
#include <cmath>
#include <time.h>
#include <vector>
@ -225,14 +286,14 @@ using namespace std;
string s0;
void addMessage(string s, char spamtype = 0);
#ifdef ANDROID
#if ISANDROID
FILE *debfile;
#endif
FILE *debugfile;
int debugflags;
#ifdef USE_COMMANDLINE
#if CAP_COMMANDLINE
const char *scorefile = "hyperrogue.log";
const char *conffile = "hyperrogue.ini";
string levelfile = "hyperrogue.lev";
@ -263,7 +324,7 @@ const char *loadlevel = NULL;
#include "game.cpp"
#include "landgen.cpp"
#include "orbs.cpp"
#ifdef INV
#if CAP_INV
#include "inventory.cpp"
#else
bool inv::on;
@ -272,11 +333,11 @@ bool inv::on;
#include "geometry.cpp"
#include "polygons.cpp"
#include "mapeditor.cpp"
#ifndef MOBILE
#if CAP_MODEL
#include "netgen.cpp"
#endif
#ifdef EXTRA
#include "extra/extra.cpp"
#if CAP_TABFONT || CAP_CREATEFONT
#include "nofont.cpp"
#endif
#include "basegraph.cpp"
#include "help.cpp"
@ -284,11 +345,8 @@ bool inv::on;
#include "scores.cpp"
#include "menus.cpp"
#include "quit.cpp"
#ifdef FIXEDSIZE
#include "nofont.cpp"
#endif
#include "shmup.cpp"
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
#include "rogueviz.cpp"
#endif
#include "conformal.cpp"
@ -299,10 +357,10 @@ bool inv::on;
#include "graph.cpp"
#include "sound.cpp"
#include "achievement.cpp"
#ifdef TOUR
#if CAP_TOUR
#include "tour.cpp"
#endif
#ifndef MOBILE
#if ISMOBILE==0
#include <unistd.h>
#endif
@ -321,7 +379,7 @@ void initAll() {
// initlanguage();
initgraph();
#ifndef NOSAVE
#if CAP_SAVE
loadsave();
#endif
resetGeometry();
@ -344,19 +402,19 @@ void initAll() {
void finishAll() {
achievement_final(!items[itOrbSafety]);
#ifndef NOSAVE
#if CAP_SAVE
saveStats();
#endif
offscreen.clear();
clearMemory();
#ifndef MOBILE
#if ISMOBILE==0
cleargraph();
#endif
achievement_close();
}
#ifdef ANDROID
#if ISANDROID
string buildScoreDescription() {
string s;
time_t timer;
@ -365,7 +423,7 @@ string buildScoreDescription() {
char buf2[128];
s += XLAT("HyperRogue for Android");
s += " ("VER"), http://www.roguetemple.com/z/hyper/\n";
s += " ( " VER "), http://www.roguetemple.com/z/hyper/\n";
s += XLAT("Date: %1 time: %2 s ", buf, its(savetime + time(NULL) - timerstart));
s += XLAT("distance: %1\n", its(celldist(cwt.c)));
// s += buf2;
@ -392,7 +450,7 @@ string buildScoreDescription() {
}
#endif
#ifdef MOBILE
#if ISMOBILE==1
bool lclicked = false, clicked = false;
string lmouseovers;
@ -406,10 +464,7 @@ void displayTexts();
void controlMusic(int ticks);
void showHelp(MOBPAR_FORMAL, string nhelp) {
help = nhelp;
// helptext = help;
lastmode = cmode;
cmode = emHelp;
gotoHelp(nhelp);
}
bool useRangedOrb;
@ -497,14 +552,14 @@ void handleclick(MOBPAR_FORMAL) {
if(andmode >= 10) andmode -= 10;
if(andmode == 3) cmode = emMenu, andmode = 0;
if(andmode == 3) pushScreen(showMainMenu), andmode = 0;
}
int touchedAt;
int getticks();
#ifdef ANDROIDSHARE
#if CAP_ANDROIDSHARE
void shareScore(MOBPAR_FORMAL);
#endif
@ -540,7 +595,7 @@ void mobile_draw(MOBPAR_FORMAL) {
if(hypot(mousex - xmove, mousey - yb) < rad) targetclick = false;
}
if(size(screens) == 1) {
if(cmode & sm::NORMAL) {
lmouseover = (gtouched && lclicked) ? mouseover : NULL;
if(!shmup::on && !useRangedOrb && vid.mobilecompasssize) {
using namespace shmupballs;
@ -570,7 +625,9 @@ void mobile_draw(MOBPAR_FORMAL) {
if(clicked && !lclicked) touchedAt = ticks;
#if CAP_XGD
graphdata.clear();
#endif
getcstat = 0; shiftmul = 1; getcshift = 1;
drawscreen();
shiftmul = getcshift;
@ -584,9 +641,9 @@ void mobile_draw(MOBPAR_FORMAL) {
bool keyreact = lclicked && !clicked;
if(cmode == emOverview || cmode == emTactic) {
if(cmode & sm::ZOOMABLE) {
using namespace dialog::zoom;
if(zoomoff || (cmode != emOverview && cmode != emTactic)) {
if(zoomoff) {
zoomf = 1; shiftx = shifty = 0; zoomoff = false; return;
}
if(clicked && !lclicked) {
@ -601,53 +658,46 @@ void mobile_draw(MOBPAR_FORMAL) {
if(inslider) keyreact = true;
#ifdef ANDROIDSHARE
#if CAP_ANDROIDSHARE
if(getcstat == 's'-96 && keyreact) {
popScreenAll().
popScreenAll();
shareScore(MOBPAR_ACTUAL);
}
#endif
if(andmode == 2 && size(screens) != 1) andmode = 12;
if((cmode == emQuit && !canmove && keyreact && lclicked && !clicked) && !buttonclicked) {
popScreenAll(); printf("back to quit\n");
}
else if(cmode == emScores) handleScoreKeys(0, 0);
else if(getcstat && keyreact) {
if(cmode == emMenu && getcstat == 'q') openURL();
else { extra ex; handlekey(getcstat, getcstat, ex); }
if((cmode & sm::NORMAL) && getcstat == '-')
getcstat = 0;
if(keyreact) {
handlekey(getcstat, getcstat);
}
#ifdef IOS
#if ISIOS
displayTexts();
#endif
if((cmode != emBasicConfig && cmode != emScores)) {
if(clicked && lclicked && andmode == 1 && !inmenu) {
if(!mouseout2() && mouseoh[2] < 50 && mouseh[2] < 50) {
panning(mouseoh, mouseh);
}
if(clicked && lclicked && andmode == 1 && (cmode & sm::NORMAL)) {
if(!mouseout2() && mouseoh[2] < 50 && mouseh[2] < 50) {
panning(mouseoh, mouseh);
}
}
if(andmode == 1 && lclicked && !clicked && !inmenu && mouseover)
performMarkCommand(mouseover);
if(andmode == 1 && lclicked && !clicked && !inmenu && mouseover)
performMarkCommand(mouseover);
if(clicked && andmode == 2 && (mouseover != lmouseover || mouseovers != lmouseovers) && !inmenu) {
addMessage(mouseovers);
lmouseovers = mouseovers;
}
if(andmode == 10 && clicked != lclicked) andmode = 0;
if(andmode == 20 && clicked != lclicked) andmode = 10;
if(clicked && andmode == 2 && (mouseover != lmouseover || mouseovers != lmouseovers) && !inmenu) {
addMessage(mouseovers);
lmouseovers = mouseovers;
}
if(andmode == 2 && lclicked && !clicked) {
if(!inmenu)
showHelp(MOBPAR_ACTUAL, help);
else if(cmode != emScores && cmode != emPickScores)
cmode = emNormal;
}
if(andmode == 10 && clicked != lclicked) andmode = 0;
if(andmode == 20 && clicked != lclicked) andmode = 10;
if(andmode == 2 && lclicked && !clicked) {
showHelp(MOBPAR_ACTUAL, help);
}
else if(andmode == 4) {
achievement_final(false);
@ -659,21 +709,19 @@ void mobile_draw(MOBPAR_FORMAL) {
lmouseovers = mouseovers;
}
}
if(clicked != lclicked)
flashMessages();
// END
lclicked = clicked;
#ifdef IOS
#if ISIOS
controlMusic(ticks - lastt);
#endif
}
#endif
#ifdef NOAUDIO
#if !CAP_AUDIO
void playSound(cell*, const string &s, int vol) { printf("play sound: %s vol %d\n", s.c_str(), vol); }
#endif

397
inventory.cpp Normal file
View File

@ -0,0 +1,397 @@
namespace inv {
bool on;
int usedup[ittypes];
int remaining[ittypes];
int rseed;
bool usedForbidden;
void init() {
rseed = hrandpos();
usedForbidden = false;
for(int i=0; i<ittypes; i++) usedup[i] = 0;
}
static const int MIRRORED = 1000;
static const int TESTMIRRORED = 900;
int mirrorqty(eItem orb) {
if(shmup::on && isShmupLifeOrb(orb))
return 3;
if(orb == itOrbWater) return 10;
if(orb == itOrbSummon) return 9;
if(orb == itOrbEmpathy) return 9;
if(orb == itOrbMatter) return 9;
if(orb == itOrbLuck) return 8;
if(orb == itOrbSpace) return 7;
if(orb == itOrbWinter) return 6;
if(orb == itOrbLife) return 6;
if(orb == itOrbLove) return 6;
if(orb == itOrbRecall) return 6;
if(orb == itOrbDigging) return 6;
if(orb == itOrbTime) return 5;
if(orb == itOrbAir) return 5;
if(orb == itOrbFish) return 5;
if(orb == itOrbStunning) return 5;
if(orb == itOrbUndeath) return 5;
if(orb == itOrb37) return 5;
if(orb == itOrbDomination) return 5;
if(orb == itOrbBull) return 5;
if(orb == itOrbHorns) return 5;
if(orb == itOrbAether) return 4;
if(orb == itOrbInvis) return 4;
if(orb == itOrbFire) return 4;
if(orb == itOrbDragon) return 4;
if(orb == itOrbIllusion) return 4;
if(orb == itOrbDiscord) return 4;
if(orb == itOrbBeauty) return 4;
if(orb == itOrbMirror) return 1;
return 3;
}
struct nextinfo { int min, real, max; };
nextinfo next[ittypes];
mt19937 invr;
void sirand(int i) {
invr.seed(i);
}
int irand(int i) {
return invr() % i;
}
void gainOrbs(eItem it, eItem o) {
int qty = items[it];
if(it == itHolyGrail) {
remaining[itOrbIllusion] += qty;
next[it] = {qty+1, qty+1, qty+1};
}
else {
bool nextfound = false;
if(qty >= 10) remaining[o]++;
else next[it] = {10,10,10}, nextfound = true;
int last = 10;
for(int k=0; k<30 || !nextfound; k++) {
int maxstep = 15 + 5 * k;
if(o == itOrbMirror)
maxstep += 5 * (k-1) * (k-2);
else
maxstep += (k-1) * (k-2);
int xnext;
if(k >= 30 || o == itOrbMirror) {
xnext = last + maxstep/2; last = xnext-1;
maxstep = 1;
}
else
xnext = last + 1 + irand(maxstep);
if(xnext > qty && !nextfound)
next[it] = { last+1, xnext, last + maxstep }, nextfound = true;
if(xnext <= qty) remaining[o]++;
last = xnext;
}
}
}
void gainMirrors(int qtl) {
while(qtl > 0) qtl >>= 1, remaining[itOrbMirror]++;
}
void compute() {
for(int i=0; i<ittypes; i++) remaining[i] = -usedup[i];
for(int i=0; i<ittypes; i++) if(usedup[i] >= TESTMIRRORED) remaining[i] += MIRRORED;
sirand(rseed);
vector<pair<eItem, eItem>> itempairs;
for(int k=0; k<ORBLINES; k++) {
auto oi = orbinfos[k];
eLand l = oi.l;
eItem it = treasureType(l);
eItem o = oi.orb;
if(oi.gchance) itempairs.emplace_back(it, o);
else if(items[it] >= 10) remaining[o]++;
}
sort(itempairs.begin(), itempairs.end());
gainOrbs(itShard, itOrbMirror);
gainOrbs(itHyperstone, itOrbMirror);
for(auto p: itempairs)
gainOrbs(p.first, p.second);
if(items[itOrbYendor]) remaining[itOrbMirror]++;
gainMirrors(items[itOrbYendor]);
gainMirrors(items[itHolyGrail]);
if(princess::reviveAt) {
remaining[itOrbLove]++;
int s = gold(NO_LOVE);
int last = princess::reviveAt;
for(int k=0;; k++) {
int nextstep = 50 + 20 * k;
last += nextstep;
if(last > s) {
next[itSavedPrincess] = {last, last, last};
break;
}
else { last += nextstep; remaining[itOrbLove]++; }
}
}
vector<eItem> offensiveOrbs = {
itOrbFlash, itOrbLightning, itOrbPsi, itOrbThorns,
itOrbFreedom, itOrbSword, itOrbSword2,
itOrbHorns, itOrbDragon, itOrbStunning
};
const int qoff = size(offensiveOrbs);
for(int i=1; i<qoff; i++) swap(offensiveOrbs[i], offensiveOrbs[irand(1+i)]);
for(int i=0; (i+1)*25 <= items[itBone]; i++)
remaining[offensiveOrbs[i%qoff]]++;
if(items[itOrbLove] && !items[itSavedPrincess]) items[itSavedPrincess] = 1;
int& r = remaining[itGreenStone];
if(items[itBone] >= 10) {
for(int i=0; i<ittypes; i++) if(i != itGreenStone) {
r += usedup[i];
if(usedup[i] >= TESTMIRRORED) r -= MIRRORED;
}
}
items[itGreenStone] += r;
usedup[itGreenStone] += r;
r = 0;
if(shmup::on) for(int i=0; i<ittypes; i++) {
if(remaining[i] && isShmupLifeOrb(eItem(i))) {
gainLife();
remaining[i]--;
usedup[i]++;
}
}
items[itInventory] = 0;
for(int i=0; i<ittypes; i++)
if(i != itGreenStone && i != itOrbYendor)
items[itInventory] += remaining[i];
}
map<char, eItem> orbmap;
string orbkeys = "zfwplSetsTaMIYgCcPOWAFydLGRUuouE.,bVNhDwWZnrvhBm0123456789";
typedef pair<int, int> pxy;
vector<pxy> orbcoord;
int sq(pxy p) {
int zz = (2*p.first+p.second)*(2*p.first+p.second) + 3*p.second*p.second;
zz *= 20; zz += abs(p.second);
zz *= 20; zz += abs(p.first);
zz *= 4; zz += (p.first>0)*2+(p.second>0);
return zz;
}
bool plain;
eItem which;
bool mirroring;
void show() {
gamescreen(2);
cmode = sm::CENTER;
orbcoord.clear();
for(int y=-3; y<=3; y++) for(int x=-4; x<=4; x++) if(x+y<=4 && x+y >= -4 && (x||y))
orbcoord.emplace_back(x,y);
sort(orbcoord.begin(), orbcoord.end(), [](pxy p1, pxy p2) {
return sq(p1) < sq(p2); });
ld rad = min(vid.xres, vid.yres) / 20;
ld rad3 = int(rad * sqrt(3));
compute();
orbmap.clear();
which = itNone;
if(plain) dialog::init(XLAT(mirroring ? "mirror what?" : "inventory"), forecolor, 150, 100);
int j = 0, oc = 6;
for(int i=0; i<ittypes; i++) {
eItem o = eItem(i);
if(itemclass(o) == IC_ORB) {
char c = orbkeys[j++];
if(remaining[i] || usedup[i]) {
orbmap[c] = o;
if(plain)
dialog::addSelItem(XLAT1(iinf[o].name), its(remaining[i]), c);
else {
auto pos = orbcoord[oc++];
ld px = vid.xres/2 + 2*rad*pos.first + rad*pos.second;
ld py = vid.yres/2 + pos.second * rad3;
int icol = iinf[o].color;
if(!remaining[i]) icol = gradient(icol, 0, 0, .5, 1);
bool gg = graphglyph();
if(!hiliteclick) {
if(gg) {
initquickqueue();
transmatrix V = atscreenpos(px, py, rad*2);
drawItemType(o, NULL, V, icol, ticks/3 + i * 137, false);
quickqueue();
}
int tcol = remaining[i] ? darkenedby(icol, 1) : 0;
if(remaining[i] != 1 || !gg)
displaystr(px, py, 2, gg?rad:rad*3/2, remaining[i] == 0 ? "X" : remaining[i] == 1 ? "o" : its(remaining[i]), tcol, 8);
}
bool b = hypot(mousex-px, mousey-py) < rad;
if(b) {
getcstat = c,
which = o;
}
}
}
}
}
if(plain) {
dialog::addBreak(750);
dialog::addItem(XLAT("help"), SDLK_F1);
dialog::addItem(XLAT("return to the game"), 'i');
dialog::display();
which = orbmap[getcstat];
}
else {
if(which == itNone) {
displaystr(vid.xres/2, vid.fsize*2, 2, vid.fsize*2, XLAT("Which orb to use?"), 0xC0C0C0, 8);
}
else {
int icol = iinf[which].color;
displaystr(vid.xres/2, vid.fsize*2, 2, vid.fsize*2, XLAT1(iinf[which].name), icol, 8);
auto oi = getOrbInfo(which);
if(mirroring)
displaystr(vid.xres/2, vid.fsize*4, 2, vid.fsize, usedup[which] >= TESTMIRRORED ? XLAT("already mirrored") : XLAT("Uses to gain: %1", its(mirrorqty(which))), icol, 8);
else {
eItem t = treasureType(oi.l);
string s = XLAT("Unlocked by: %1 in %2", t, oi.l);
if(next[t].min == next[t].max)
s += XLAT(" (next at %1)", its(next[t].min));
else
s += XLAT(" (next at %1 to %2)", its(next[t].min), its(next[t].max));
displaystr(vid.xres/2, vid.fsize*4, 2, vid.fsize, s, icol, 8);
}
if(remaining[which] != 1)
displaystr(vid.xres/2, vid.fsize*5, 2, vid.fsize, XLAT("Number of uses left: %1", its(remaining[which])), icol, 8);
#if ISMOBILE==0
string hot = XLAT1("Hotkey: "); hot += getcstat;
displaystr(vid.xres/2, vid.fsize*6, 2, vid.fsize, hot, icol, 8);
#endif
eOrbLandRelation olr = getOLR(oi.orb, getPrizeLand());
eItem tr = treasureType(oi.l);
int col = 0;
if(olr == olrDangerous) col = 0xC00000;
if(olr == olrUseless) col = 0x808080;
if(olr == olrForbidden) col = 0x804000;
if(col)
displaystr(vid.xres/2, vid.yres - vid.fsize*4, 2, vid.fsize, XLAT(olrDescriptions[olr], cwt.c->land, tr, treasureType(cwt.c->land)), col, 8);
dialog::displayPageButtons(3, 0);
}
}
mouseovers = "";
keyhandler = [] (int sym, int uni) {
if(plain) dialog::handleNavigation(sym, uni);
if(orbmap.count(uni)) {
eItem orb = orbmap[uni];
if(!remaining[orb]) ;
else if(orb == itOrbMirror) {
mirroring = !mirroring;
// an amusing message
if(remaining[itOrbMirror] >= 2 && !mirroring)
addMessage(XLAT("You mirror %the1.", orb));
if(mirroring) {
bool next = false;
forCellEx(c2, cwt.c) if(c2->wall == waMirror || c2->wall == waCloud || c2->wall == waMirrorWall)
next = true;
if(!next) {
addMessage("You need to stand next to a magic mirror or cloud to use %the1.", itOrbMirror);
mirroring = false;
}
}
}
else if(mirroring) {
if(usedup[orb] >= TESTMIRRORED) {
addMessage("Each orb type can be mirrored only once.");
mirroring = false;
}
else if(remaining[orb]) {
usedup[itOrbMirror]++;
usedup[orb] += MIRRORED;
usedup[orb] -= mirrorqty(orb);
usedup[itGreenStone]--;
addMessage(XLAT("You mirror %the1.", orb));
mirroring = false;
}
else mirroring = false;
}
else if((isHaunted(cwt.c->land) || cwt.c->land == laDungeon) && orb == itOrbSafety) {
addMessage(XLAT("This would only move you deeper into the trap!"));
}
else {
eItem it = cwt.c->item;
cwt.c->item = orbmap[uni];
collectItem(cwt.c, true);
if(!cwt.c->item) usedup[orbmap[uni]]++;
if(getOLR(it, getPrizeLand()))
usedForbidden = true;
cwt.c->item = it;
checkmove();
popScreenAll();
}
}
else if(uni == '1') plain = !plain;
else if(sym == SDLK_F1)
gotoHelp(which ? generateHelpForItem(which) : NODESCYET);
else if(doexiton(sym, uni)) popScreen();
};
}
void applyBox(eItem it) {
applyBoxNum(usedup[it]);
}
int incheck;
void check(int delta) {
incheck += delta;
for(int i=0; i<ittypes; i++) {
eItem it = eItem(i);
if(itemclass(it) == IC_ORB)
items[it] += delta * remaining[it] * orbcharges(it);
}
}
}

View File

@ -71,7 +71,10 @@ int isNative(eLand l, eMonster m) {
return (m == moSlime) ? 2 : 0;
case laMirror: case laMirrored: case laMirrorWall: case laMirrorWall2: case laMirrored2:
return (m == moEagle || m == moRanger || m == moMirror || m == moMirage) ? 1 : 0;
return (m == moMirrorSpirit || m == moNarciss || m == moMimic) ? 1 : 0;
case laMirrorOld:
return (m == moEagle || m == moRanger || m == moMimic) ? 1 : 0;
case laMotion:
return (m == moRunDog) ? 2 : 0;
@ -232,6 +235,7 @@ eItem treasureType(eLand l) {
case laAlchemist: return itElixir;
case laMirror: case laMirrored: case laMirrorWall: case laMirrorWall2: case laMirrored2:
case laMirrorOld:
return itShard;
case laMotion: return itFeather;
@ -317,6 +321,7 @@ eItem wanderingTreasure(cell *c) {
if(l == laEEarth) return itEarthShard;
if(l == laElementalWall) return itNone;
if(l == laMirror && c->type != 6) return itNone;
if(l == laMirrorOld && c->type != 6) return itNone;
if(l == laEmerald) {
forCellEx(c2, c) if(c2->wall == waCavewall) return itNone;
}
@ -399,7 +404,7 @@ bool isElemental(eLand l);
eItem orbType(eLand l) {
if(isElemental(l)) l = laElementalWall;
if(l == laMirror) return itShard;
if(l == laMirror || l == laMirrorOld) return itShard;
for(int i=0; i<ORBLINES; i++)
if(orbinfos[i].l == l && orbinfos[i].gchance)
return orbinfos[i].orb;
@ -705,6 +710,9 @@ bool landUnlocked(eLand l) {
case laBarrier: case laNone: case laOceanWall: case laCanvas: case laCA:
return false;
case laMirrorOld:
return false;
case laHaunted: case laHauntedWall: case laHauntedBorder:
return items[itBone] >= U10;
@ -1591,7 +1599,7 @@ void chasmifyElemental(cell *c) {
bool incompatible1(eLand l1, eLand l2) {
if(isCrossroads(l1) && isCrossroads(l2)) return true;
if(l1 == laJungle && l2 == laMotion) return true;
if(l1 == laMirror && l2 == laMotion) return true;
if(l1 == laMirrorOld && l2 == laMotion) return true;
if(l1 == laPower && l2 == laWineyard) return true;
if(l1 == laPower && l2 == laDryForest) return true;
if(l1 == laDragon && l2 == laDryForest) return true;
@ -1714,11 +1722,11 @@ hookset<eLand(eLand)> *hooks_nextland;
eLand getNewLand(eLand old) {
if(old == laMirror && !chaosmode && hrand(10) < 8) return laMirrored;
eLand l = callhandlers(laNone, hooks_nextland, old);
if(l) return l;
if(old == laMirror && !oldmirror && hrand(10)) return laMirrored;
if(cheatdest != old) if(!isCyclic(cheatdest) && !isTechnicalLand(cheatdest)) return cheatdest;
if(old == laTortoise) return laDragon;
@ -2119,6 +2127,8 @@ bool buildBarrier6(cellwalker cw, int type) {
}
if(purehepta && false) {
for(int z=0; z<4; z++)
b[z].c->item = eItem(1+z+4*type);
for(int a=0; a<4; a++)
extendBarrierBack(cwpeek(b[a],0));
}
@ -2529,8 +2539,8 @@ bool checkInTree(cell *c, int maxv) {
void buildEquidistant(cell *c) {
if(!c) return;
if(c->landparam) return;
if(chaosmode) return;
eLand b = c->land;
if(chaosmode && !inmirror(b)) return;
if(!b) {
printf("land missing at %p\n", c);
describeCell(c);
@ -2929,7 +2939,7 @@ void setLandQuotient(cell *c) {
bool quickfind(eLand l) {
if(l == cheatdest) return true;
#ifdef TOUR
#if CAP_TOUR
if(tour::on && tour::quickfind(l)) return true;
#endif
return false;
@ -3098,8 +3108,12 @@ void buildBigStuff(cell *c, cell *from) {
// buildgreatwalls
if(chaosmode) {
if(c->type == 7 && hrand(10000) < 9000 && c->land && buildBarrierNowall(c, getNewLand(c->land)))
if(c->type == 7 && hrand(10000) < 9000 && c->land && !inmirror(c) && buildBarrierNowall(c, getNewLand(c->land)))
{}
else if(c->type == 7 && c->land == laMirror && hrand(10000) < 2000) {
int bd = 2 + hrand(2) * 3;
buildBarrier(c, bd, laMirrored);
}
}
else if(c->type == 7 && isWarped(c->land) && hrand(10000) < 3000 && c->land &&
@ -3157,7 +3171,7 @@ void buildBigStuff(cell *c, cell *from) {
(c->land == laGraveyard && items[itBone] >= 10) ? 120 :
c->land == laOcean ? (deepOcean ? (purehepta ? 250 : 2000) : 0) :
c->land == laDragon ? 120 :
(c->land == laMirror && !oldmirror) ? 6000 :
(c->land == laMirror && !yendor::generating) ? 6000 :
50))
{
@ -3511,8 +3525,6 @@ void setdist(cell *c, int d, cell *from) {
if(d <= 3) lastexplore = shmup::on ? shmup::curtime : turncount;
oldmirror = euclid || chaosmode || yendor::on || yendor::generating;
if(buggyGeneration) {
if(d < BARLEV) for(int i=0; i<c->type; i++) {
setdist(createMov(c, i), d+(purehepta?2:1), c);
@ -5294,18 +5306,28 @@ void setdist(cell *c, int d, cell *from) {
if(c->land == laMirrored || c->land == laMirrorWall || c->land == laMirrorWall2 ||
c->land == laMirrored2)
c->wall = waMirrorWall;
if(c->land == laMirror) {
int freqt = oldmirror ? 1 : 4;
int freqm = (oldmirror || cwt.c->land != laMirror) ? 1 : 30;
if((purehepta?pseudohept(c):!ishept(c)) && hrand(5000/freqt) < 120 && notDippingFor(itShard))
if(c->land == laMirrorOld) {
if((purehepta?pseudohept(c):!ishept(c)) && hrand(5000) < 120 && (peace::on || notDippingFor(itShard)))
c->wall = hrand(2) ? waMirror : waCloud;
else if(ishept(c) && hrand(5000/freqt) < 10 * PRIZEMUL)
else if(ishept(c) && hrand(5000) < 10 * PRIZEMUL)
placePrizeOrb(c);
else if(hrand(12000/freqt) < 8 + items[itShard] + hard)
else if(hrand(12000) < 8 + items[itShard] + hard)
c->monst = moRanger;
else if(hrand(60000/freqm) < 8 + items[itShard] + hard)
else if(hrand(60000) < 8 + items[itShard] + hard)
c->monst = moEagle;
}
if(c->land == laMirror) {
if((purehepta?pseudohept(c):!ishept(c)) && hrand(1250) < 120 && (peace::on || notDippingFor(itShard)))
c->wall = hrand(2) ? waMirror : waCloud;
else if(ishept(c) && hrand(5000) < 10 * PRIZEMUL)
placePrizeOrb(c);
else if(hrand(600) < 8 + items[itShard] + hard) {
if(items[itShard] >= 5 && hrand(120) <= 20)
c->monst = moMirrorSpirit;
else
c->monst = moNarciss;
}
}
if(c->land == laGraveyard) {
if(hrand(5000) < PT(30 + 4*kills[moZombie] + 6*kills[moNecromancer], 120) && notDippingFor(itBone))
c->item = itBone;
@ -5437,9 +5459,12 @@ void setdist(cell *c, int d, cell *from) {
}
}
if(purehepta && c->wall == waMirrorWall && c->land == laMirror)
c->land = laMirrorWall; // , c->item = itPirate; // not really a proper bugfix
if(d == 7) playSeenSound(c);
#ifndef NOEDIT
#if CAP_EDIT
if(d >= 7 && mapeditor::whichPattern)
mapeditor::applyModelcell(c);
#endif
@ -5714,9 +5739,17 @@ void wandering() {
else if(c->land == laJungle && wchance(items[itRuby], 40))
c->monst = hrand(10) ? moMonkey : moEagle;
else if(c->land == laMirror && wchance(items[itShard], 15))
else if(c->land == laMirrorOld && wchance(items[itShard], 15))
c->monst = hrand(10) ? moRanger : moEagle;
else if(c->land == laMirror && mirrorspirits) {
mirrorspirits--;
c->monst = moMirrorSpirit;
}
else if(c->land == laMirror && wchance(items[itShard], 120))
c->monst = moNarciss;
else if(c->land == laWarpCoast && wchance(items[itCoral], 40))
c->monst = moRatling;
@ -6149,12 +6182,12 @@ namespace halloween {
}
int id = hrand(100);
if(items[itTreat] == 1) {
#ifndef MOBILE
#if ISMOBILE==0
addMessage(XLAT("Hint: use arrow keys to scroll."));
#endif
}
else if(items[itTreat] == 2) {
#ifndef MOBILE
#if ISMOBILE==0
addMessage(XLAT("Hint: press 1 2 3 4 to change the projection."));
#endif
}

View File

@ -375,7 +375,7 @@ S("Hyperstone Quest: collect at least %3 %1 in %the2", "Hyperkamový úkol: sesb
S("Hyperstone Quest completed!", "Hyperkamový úkol splněn!")
S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Hledej Yendorské sféry v Pekle nebo na Křižovatce!")
S("Unlock the Orb of Yendor!", "Odemkni Yendorskou sféru!")
S("Defeat 100 enemies to access the Graveyard", "Hřbitov zpřístupníš poražením 100 nepřátel")
S("Defeat %1 enemies to access the Graveyard", "Hřbitov zpřístupníš poražením %1 nepřátel")
S("(press ESC during the game to review your quest)", "(své úkoly můžeš během hry zobrazit stiskem ESC)")
S("you have cheated %1 times", "počet cheatů: %1")
S("%1 turns (%2)", "počet kol: %1 (%2)")
@ -5171,7 +5171,7 @@ S("The game starts in the Icy Lands. Collect the Ice Diamonds "
S("Hypersian Rug model", "Model hyperského koberce")
S(
"New players think that the action of HyperRogue takes place on a sphere. "
#ifdef MOBWEB
#if ISMOBWEB
"This is not true -- try the Tutorial in the native desktop version shows "
"the surface HyperRogue actually takes place on.",
#else
@ -5183,7 +5183,7 @@ S(
"Noví hráči si často myslí, že se HyperRogue odehrává na povrchu koule. "
#ifdef MOBWEB
#if ISMOBWEB
"Není to pravda -- Tutoriál v desktopové verzi ti může ukázat povrch, "
"na jakém se HyperRogue opravdu odehrává."
#else
@ -5273,7 +5273,7 @@ S(
"it will appear to go slower -- this is because you are running "
"in a straight line, and the Running Dog has to run in a curve "
"called an equidistant.\n\n"
#ifdef MAC
#if ISMAC
"Remember that you can click with right Shift on anything to get more information.",
#else
"Remember that you can right click on anything to get more information.",
@ -5283,7 +5283,7 @@ S(
"Běžící pes. I když běží stejně rychle jako ty, bude se zdát, že je "
"pomalejší -- to proto, že ty běžíš po přímce, zatímco Běžící pes musí "
"běžet po křivce zvané 'ekvidistanta'.\n\n"
#ifdef MAC
#if ISMAC
"Nezapomeň, že pokud na cokoli klikneš s pravým shiftem, můžeš o tom "
"získat víc informací."
#else
@ -5510,5 +5510,363 @@ S(
"Stisknutím klávesy '5' opustíš tutoriál."
)
// Orb Strategy mode
S("Orb Strategy mode", "sférostrategický mód")
S(
"You are playing in the Orb Strategy Mode. Collecting treasure "
"gives you access to magical Orb powers. In this mode, "
"unlocking requirements are generally higher, and "
"several quests and lands "
"give you extremely powerful Orbs of the Mirror.\n",
"Právì hraješ ve sférostrategickém módu. Sbírání pokladù ti dá pøístup "
"k magickým silám Sfér. V tomto módu jsou požadavky na odemykání nových "
"vìcí obecnì vyšší a nìkolik úkolù a krajù ti dává nesmírnì silné Sféry "
"Zrcadla.\n")
S("The treasure gives your magical powers!", "Poklady ti dávají magickou sílu!")
S("Press 'i' to access your magical powers.", "Stiskem klávesy 'i' pøejdeš na svou magickou sílu.")
S("inventory", "Tvé Sféry")
S("mirror what?", "co chceš zrcadlit?")
S("Which orb to use?", "Kterou Sféru chceš použít?")
S("Unlocked by: %1 in %2", "Odemèeno pøi: %1 %abl2")
S(" (next at %1)", " (další pøi %1)")
S(" (next at %1 to %2)", " (další pøi %1 až %2)")
S("Number of uses left: %1", "Poèet zbývajících použití: %1")
S("You mirror %the1.", "Zrcadlíš %a1.")
S("You need to stand next to a magic mirror or cloud to use %the1.",
"Abys mohl použít %a1, musíš stát vedle kouzelného zrcadla nebo oblaku.")
S("Each orb type can be mirrored only once.", "Každý typ Sféry lze zrcadlit pouze jednou.")
S(
"\n\nIn the Orb Strategy Mode, Orbs of Yendor appear in Hell after "
"you collect 25 Demon Daisies in Hell, in Crossroads/Ocean after you collect 50, "
"and everywhere after you collect 100.",
"\n\nVe sférostrategickém módu se Yendorské Sféry objevují v Pekle poté, "
"co tam získáš 25 Èertových kvítek. Po získání 50 Èertových kvítek se "
"zaènou objevovat na Køižovatce a v Oceánu, a po získání 100 Èertových "
"kvítek všude."
);
S(
"\n\nIn the Orb Strategy Mode, dead orbs are available once you collect "
"10 Necromancer Totems in the Graveyard.",
"\n\nMrtvé Sféry se ve sférostrategickém módu objevují poté, co získáš "
"10 Nekromancerových totemù na Høbitovì.")
S(
"\n\nIn the Orb Strategy Mode, Orbs of Safety can be gained by "
"collecting Phoenix Feathers in the Land of Eternal Motion. "
"You can also find unlimited Orbs of Safety in the Crossroads "
"and the Ocean (after collecting 25 Phoenix Feathers) "
"and in the Prairie.",
"\n\nVe sférostrategickém módu mùžeš získat Sféry Bezpeènosti sbíráním "
"Fénixových pírek v Kraji vìèného pohybu. Také jich mùžeš najít neomezenì "
"mnoho na Køižovatce a v Oceánu (ale musíš nejprve získat 25 Fénixových "
"pírek) a na Prérii."
)
S(
"\n\nCollect %the1 to gain an extra Orb of the Mirror. "
"You can gain further Orbs of the Mirror by collecting 2, 4, 8...",
"\n\nKdyž získáš %a1, dostaneš další Sféru Zrcadla. "
"Další Sféry Zrcadla pak mùžeš získat za 2, 4, 8..."
)
S(
"\n\nIn the Orb Strategy Mode, the Orb of Luck also "
"significantly increases the frequency of Great Walls, Crossroads IV, "
"and sub-lands.",
"\n\nVe sférostrategickém módu Sféra Štìstí také výraznì zvyšuje frekvenci Velkých zdí, Køižovatek IV a podkrajù.")
S("\n\nIn the Orb Strategy Mode, each 25 Necromancer's Totems "
"you are given a random offensive Orb.",
"\n\nVe sférostrategickém módu ti každých 25 Nekromancerových "
"totemù pøidá jednu náhodnou útoènou Sféru.")
S(
"Use Orb of the Mirror to gain copies of one of your Orbs; "
"mirroring weaker Orbs usually yields more copies. "
"It can only be used once per Orb type, "
"and only when you are next to a mirror.",
"Sféru Zrcadla mùžeš použít ke kopírování ostatních Sfér; ze slabších "
"Sfér obvykle získáš více kopií. Toto lze s každým typem Sféry udìlat "
"pouze jednou, a pouze tehdy, když stojíš vedle zrcadla.")
S("Uses to gain: %1", "Získáš použití: %1")
S("already mirrored", "již zrcadleno")
N("your orbs", GEN_F, "Tvé Sféry", "Tvé Sféry", "Tvé Sféry", "Tvé Sféry")
S("Click this to see your orbs.", "Kliknutím zde zobrazíš své Sféry.")
// peaceful mode
S("configure keys/joysticks", "konfigurace kláves/joysticku")
S("peaceful mode", "klidný mód")
// config changes
S("Press F5 or 'o' to try again!", "Stiskem F5 nebo 'o' to mùžeš zkusit znovu!")
S("aura brightness", "jas aury")
S("aura smoothening factor", "vyhlazovací faktor aury")
S("graphics configuration", "konfigurace grafiky")
S("special display modes", "zvláštní zobrazovací módy")
S("openGL mode", "mód OpenGL")
S("anti-aliasing", "anti-aliasing")
S("line width", "šíøka èar")
S("configure panning and general keys", "konfigurace pøejíždìní a obecných kláves")
S("\n\nHint: use 'm' to toggle cells quickly",
"\n\nTip: políèka lze rychle pøepínat klávesou 'm'");
// cell pattern names
S("football", "fotbal")
S("dark rainbow landscape", "temná duha")
S("field pattern", "vzor pole")
S("field pattern C", "vzor pole C")
S("field pattern D", "vzor pole D")
S("field pattern N", "vzor pole N")
S("field pattern S", "vzor pole S")
S("four triangles", "ètyøi trojúhelníky")
S("big triangles: rings", "velké trojúhelníky: prstence")
// missing for the Tutorial
S("tutorial", "tutoriál")
S("This Orb is not compatible with the Tutorial.", "Tato Sféra není kompatibilní s tutoriálem.")
// local scores
S("turns", "kol")
S("cells", "políèek")
S("sort", "tøídìní")
S("choose", "výbìr")
S("play", "hraj")
// draw editor
S("autochoose", "autovýbìr")
S("c = choose", "c = výbìr")
S("b = switch auto", "b = pøepni auto")
// mission screen hints
S(
"If you collect too many treasures in a given land, it will become "
"extremely dangerous. Try other lands once you have enough!",
"Pokud získáš pøíliš mnoho pokladù v jednom kraji, zaène být velmi "
"nebezpeèný. Až budeš mít dost, zkus jiné kraje!");
S(
"Remember that you can right click almost anything for more information.",
"Nezapomeò, že témìø na všechno mùžeš kliknout pravým tlaèítkem a získat "
"o tom více informací.")
S("Want to understand the geometry in HyperRogue? Try the Tutorial!",
"Chceš porozumìt geometrii v HyperRogue? Zkus Tutoriál!");
S(
"Collecting 25 treasures in a given land may be dangerous, "
"but allows magical Orbs of this land to appear in other places!",
"Získat 25 pokladù v jednom kraji mùže být nebezpeèné, ale zpùsobí "
"to, že se magické Sféry z tohoto kraje zaènou objevovat i v jiných!")
S(
"Press ESC to view this screen during the game.",
"Tuto obrazovku mùžeš bìhem hry zobrazit stiskem ESC.")
S("The 'world overview' shows all the lands in HyperRogue.",
"'Pøehled krajù' ti ukáže všechny kraje v HyperRogue."
)
S("Press 'o' to see all the lands in HyperRogue.",
"Stiskem 'o', zobrazíš všechny kraje v HyperRogue.")
S(
"Want another type of game? Want more challenge?\n"
"HyperRogue has many special modes and challenges that "
"significantly change the gameplay. Try them!",
"Chceš jiný typ hry? Chceš vìtší výzvu?\n"
"HyperRogue obsahuje øadu zvláštních módù a výzev, které "
"výraznì mìní styl hry. Zkus je!")
S(
"Hyperbolic geometry can be shown in many ways.",
"Hyperbolickou geometrii je možné ukázat mnoha zpùsoby...")
S(
"You do not want to lose the game from a single mistake?\n"
"Do you want to use the Orbs strategically?\n"
"Try the Orb Strategy mode!",
"Nechceš prohrát kvùli jedné chybì?\n"
"Chceš používat Sféry strategicky\n"
"Zkus Sférostrategický mód!")
S(
"Do you think you are playing on a ball? "
"This is far from the truth!\n",
"Myslíš, že hraješ na kouli? Samá voda!\n")
S(
"Did you know that the path you take during the game "
"is usually very close to a straight line?\n",
"Vìdìl jsi, že cesta, kterou bìhem hry urazíš, je "
"obvykle velmi blízká pøímce?")
S("Show me!", "Ukaž!")
S(
"You are %1 cells away from the starting point, or "
"the place where you used an Orb of Safety last time. "
"There are %2 such cells.\n",
"Nacházíš se %1 políèek od výchozího bodu nebo od místa, "
"kde jsi naposledy použil Sféru Bezpeènosti. Takových "
"políèek je celkem %2.\n")
S("about ", "zhruba ")
S(" (%1 more digits)", " (%1 dalších èíslic)")
S("see how it ended", "podívej se, jak to skonèilo")
// other missing/new things
S("\n\nOrb unlocked: %1", "\n\nByla odemèena Sféra: %1")
S("Orb unlocked: %1", "Byla odemèena Sféra: %1")
S("\n\nSecondary orb: %1", "\n\nSekundární Sféra: %1")
S(" to submerge", " do ponoøení")
S(" to surface", " do vynoøení")
S("%The1 says, \"not this place, it looks even worse...\"",
"%The1 øíká, \"tady ne, tohle vypadá ještì hùø...\"")
S("torus", "torus")
S(" (click to use)", " (použij kliknutím)")
N("Hall of Mirrors", GEN_F, "Zrcadlový sál", "Zrcadlové sály", "Zrcadlový sál", "v Zrcadlovém sále")
Orb("the Mirror", "Zrcadla")
N("Reflection", GEN_O, "Odraz", "Odrazy", "Odraz", "v Odraze")
N("mirror wall", GEN_F, "zrcadlová stìna", "zrcadlové stìny", "zrcadlovou stìnu", "zrcadlovou stìnou")
S("This would only move you deeper into the trap!",
"Tím by ses jen dostal dál do pasti!");
S("You swing your sword at the mirror.", "Udeøil jsi meèem do zrcadla.");
N("Mimic", GEN_M, "Mimik", "Mimikové", "Mimika", "Mimikem")
N("Narcissist", GEN_M, "Narcis", "Narcisové", "Narcisa", "Narcisem")
N("Mirror Spirit", GEN_M, "Zrcadlový duch", "Zrcadloví duchové", "Zrcadlového ducha", "Zrcadlovým duchem")
S("This person loves to look at their own reflection in the mirror. "
"He believes himself to be one of the most important creatures in this world, "
"and hates those who do not admire him.",
"Tenhle èlovìk se rád kochá svým odrazem v zrcadle. Myslí si, že "
"je jedním z nejdùležitìjších tvorù na svìtì a nenávidí ty, "
"kteøí ho neobdivují."
)
S(
"A long time ago a mighty warrior was guarding the mirrors from being broken. "
"While this warrior is no longer alive, his reflections have gained life of "
"their own, and will punish the intruders.\n\n"
"If you attack a Mirror Spirit physically, it is delayed, but not destroyed -- "
"more reflections will come out of the mirror. Use Mimics to destroy them.",
"Tento mocný váleèník kdysi dávno støežil zrcadla, aby se nerozbila. "
"Teï už nežije, ale jeho odrazy získaly svùj vlastní život a trestají vetøelce.\n\n"
"Pokud na Zrcadlového ducha fyzicky zaútoèíš, zpomalíš ho tím, ale neznièíš "
"-- ze zrcadla vyjdou další odrazy. Pokud ho chceš znièit nadobro, použij Mimiky.")
S(" (25 in the Orb Strategy mode)", " (25 ve Sférostrategickém módu)")
S(" (50 in the Orb Strategy mode)", " (50 ve Sférostrategickém módu)")
S(" (not in the Orb Strategy mode)", " (ne ve Sférostrategickém módu)")
/*
"NEW_ACHIEVEMENT_8_19_NAME" "Totální vítìzství"
"NEW_ACHIEVEMENT_8_19_DESC" "Získej ve Sférostrategickém módu Yendorskou Sféru, Svatý grál, Princeznu a 50 Hyperkamù."
added to old achievements:
"(nebo 25 ve Sférostrategickém módu)"
"(nebo 50 ve Sférostrategickém módu)"
"(ne ve Sférostrategickém módu)"
These apparently have not been yet translated:
"NEW_ACHIEVEMENT_8_4_NAME" "Yendorský adept"
"NEW_ACHIEVEMENT_8_4_DESC" "Dokonèi Yendorskou výzvu."
"NEW_ACHIEVEMENT_8_5_NAME" "Mistr klíèù"
"NEW_ACHIEVEMENT_8_5_DESC" "Dokonèi pìt Yendorských výzev."
"NEW_ACHIEVEMENT_8_6_NAME" "Velmistr klíèù"
"NEW_ACHIEVEMENT_8_6_DESC" "Dokonèi 15 Yendorských výzev."
"NEW_ACHIEVEMENT_8_7_NAME" "Adept taktiky"
"NEW_ACHIEVEMENT_8_7_DESC" "Získej 1000 bodù v Taktickém módu."
"NEW_ACHIEVEMENT_8_8_NAME" "Mistr taktiky"
"NEW_ACHIEVEMENT_8_8_DESC" "Získej 5000 bodù v Taktickém módu."
"NEW_ACHIEVEMENT_8_9_NAME" "Velmistr taktiky"
"NEW_ACHIEVEMENT_8_9_DESC" "Získej 15 000 bodù v Taktickém módu"
"NEW_ACHIEVEMENT_8_10_NAME" "Na druhé stranì"
"NEW_ACHIEVEMENT_8_10_DESC" "Najdi a získej Zelenou trávu."
*/
#undef Orb
// peaceful texts
S("memory game", "hra na paměť")
S("display hints", "zobrazovat tipy")
S("hyperbolic puzzles", "hyperbolické hádanky")
// missing descriptions
S( "A strange land filled with mirrors. "
"Break magic mirrors and enter clouds of mirage to "
"gain treasures and helpful Mimics.",
"Podivná země plná zrcadel. "
"Rozbíjením kouzelných zrcadel a procházením oblaků přeludů "
"získáš poklady a užitečné Mimiky.")
S(
"A perfect mirror wall. It is unbreakable "
"and impassable "
"even for aethereal beings, and everything "
"you see inside is just an image of "
"the real world; you can swing your sword "
"at them, but that will not destroy them "
"in the real world. "
"Mirror walls reflect Mimics, lightning bolts, and "
"missiles perfectly.",
"Dokonalá zrcadlová stěna. Je nerozbitná a neprostupná, "
"a to i pro éterické bytosti. Všechno, co v ní vidíš, je "
"pouhý obraz reálného světa; můžeš do toho bít mečem, "
"ale v reálném světě se nic nestane. Zrcadlové stěny "
"dokonale odrážejí Mimiky, blesky a střely."
)
S(
"In the peaceful mode, you just explore the world, "
"without any battles; there are also several "
"navigational puzzles available. In the memory game, "
"you have to collect as many Dodecahedra as you can, "
"and return to the starting point -- hyperbolic geometry "
"makes this extremely difficult! Other hyperbolic puzzles "
"include the Burial Grounds (excavate the treasures "
"using your magical sword), Galápagos (try to find an adult "
"tortoise matching the baby), Camelot (find the center of "
"a large hyperbolic circle), and Palace (follow the mouse). "
"Other places listed are for exploration.",
"V klidném módu můžeš prostě jen zkoumat svět bez jakýchkoli bitev; "
"je v něm také k dispozici několik navigačních hádanek. V paměťové "
"hře musíš sesbírat co možná nejvíc Dvanáctistěnů a vrátit se do "
"výchozího bodu -- to je v hyperbolické geometrii nesmírně obtížné! "
"Další hyperbolické hádanky zahrnují Pohřebiště (vykopávání pokladů "
"magickým mečem), Galapágy (hledání dospělé želvy, která odpovídá "
"tvé želvičce), Camelot (nalezení středu velkého hyperbolického "
"kruhu) a Palác (sledování myši). Jiná uvedená místa se dají "
"zkoumat.")
S("puzzles and exploration", "hádanky a zkoumání")

View File

@ -341,7 +341,7 @@ S("Hyperstone Quest: collect at least %3 %1 in %the2", "Hyperstein-Herausforderu
S("Hyperstone Quest completed!", "Hyperstein-Herausforderung abgeschlossen!")
S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Such die Orbs von Yendor in der Hölle oder auf den Kreuzungen!")
S("Unlock the Orb of Yendor!", "Öffne den Orb von Yendor!")
S("Defeat 100 enemies to access the Graveyard", "Töte 100 Gegner um Zugang zum Friedhof zu erhalten")
S("Defeat %1 enemies to access the Graveyard", "Töte %1 Gegner um Zugang zum Friedhof zu erhalten")
S("(press ESC during the game to review your quest)", "(Drücke ESC während des Spiels, um deine aktuelle Quest anzuzeigen)")
S("you have cheated %1 times", "Du hast %1 mal Cheats benutzt")
S("%1 turns (%2)", "%1 Züge (%2)")
@ -470,8 +470,7 @@ S("Usually, you move by touching somewhere on the map; you can also touch one "
"vier Knöpfe in den Ecken antippen um dies zu ändern (um die Karte zu scrollen oder Infos "
"über Objekte zu bekommen). Du kannst auch die Zahlen antippen um ihre Bedeutung zu erfahren.\n")
S("Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. "
"To save the game you need an Orb of Safety. Press 'v' for config, ESC for the quest status and menu.\n\n",
S("Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. To save the game you need an Orb of Safety. Press 'v' for the main menu (configuration, special modes, etc.), ESC for the quest status.\n\n",
"Bewege dich mit der Maus, dem Numpad, qweadzxc, oder hjklyubn. Warte mit 's' oder '.'. Drehe die Welt mit den Pfeiltasten, Bild auf/ab und Pos1/Space. " // FIXME: Leertaste?
"Um zu speichern, benötigst du einen Orb der Geborgenheit. Drücke V für Einstellungen, ESC für den Quest-Status und das Menü.\n\n")

View File

@ -5107,7 +5107,7 @@ S("The game starts in the Icy Lands. Collect the Ice Diamonds "
S("Hypersian Rug model", "Model Hiperskiego Dywanu")
S(
"New players think that the action of HyperRogue takes place on a sphere. "
#ifdef MOBWEB
#if ISMOBWEB
"This is not true -- the Tutorial in the native desktop version shows "
"the surface HyperRogue actually takes place on.",
#else
@ -5119,7 +5119,7 @@ S(
"Nowi gracze myślą, że akcja HyperRogue toczy się na sferze. "
#ifdef MOBWEB
#if ISMOBWEB
"To nieprawda -- Podręcznik w komputerowej wersji wykonywalnej "
"pokazuje powierzchnię, na której w rzeczywistości toczy się rozgrywka."
#else
@ -5205,7 +5205,7 @@ S(
"it will appear to go slower -- this is because you are running "
"in a straight line, and the Running Dog has to run in a curve "
"called an equidistant.\n\n"
#ifdef MAC
#if ISMAC
"Remember that you can click with right Shift on anything to get more information.",
#else
"Remember that you can right click on anything to get more information.",
@ -5216,7 +5216,7 @@ S(
"Mimo że Pies biegnie z tą samą prędkością, nie będzie "
"w stanie Cię dogonić -- ponieważ Ty ruszasz się w linii prostej, "
"a Pies biegnie po krzywej zwanej ekwidystantą.\n\n"
#ifdef MAC
#if ISMAC
"Pamiętaj, że możesz klikać z prawym Shiftem na różnych elementach gry, by dowiedzieć się o nich więcej."
#else
"Pamiętaj, że możesz klikać prawym przyciskiem na różnych elementach gry, by dowiedzieć się o nich więcej."
@ -5597,7 +5597,7 @@ S(
"bardzo niebezpieczna. Spróbuj pójść do innych krain, gdy masz dość!");
S(
"Remember that you can right click mostly anything for more information.",
"Remember that you can right click almost anything for more information.",
"Pamiętaj, że prawie wszystko możesz kliknąć prawym przyciskiem, "
"by dowiedzieć się czegoś na dany temat.")
@ -5690,5 +5690,95 @@ N("mirror wall", GEN_F, "lustrzana ściana", "lustrzane ściany", "lustrzaną ś
S("This would only move you deeper into the trap!",
"To tylko przeniesie Cię w głąb pułapki!");
S("You swing your sword at the mirror.", "Wywijasz mieczem w kierunku lustra.");
N("Mimic", GEN_M, "Mimik", "Mimiki", "Mimika", "Mimikiem")
N("Narcissist", GEN_M, "Narcyz", "Narcyzy", "Narcyza", "Narcyzem")
N("Mirror Spirit", GEN_M, "Duch Lustra", "Duchy Lustra", "Ducha Lustra", "Duchem Lustra")
S("This person loves to look at their own reflection in the mirror. "
"He believes himself to be one of the most important creatures in this world, "
"and hates those who do not admire him.",
"Ten osobnik kocha patrzeć na własne lustrzane odbicie. "
"Uważa się za jedną z najważniejszych istot na świecie, "
"i nienawidzi tych, którzy go nie podziwiają."
)
S(
"A long time ago a mighty warrior was guarding the mirrors from being broken. "
"While this warrior is no longer alive, his reflections have gained life of "
"their own, and will punish the intruders.\n\n"
"If you attack a Mirror Spirit physically, it is delayed, but not destroyed -- "
"more reflections will come out of the mirror. Use Mimics to destroy them.",
"Dawno, dawno temu potężny wojownik bronił lustr przed tymi, co chcieli "
"jej rozbić. Wojownik ten już dawno nie żyje, ale jego odbicia zaczęły "
"żyć własnym życiem i karać najeźdźców.\n\n"
"Jeśli zaatakujesz Ducha Lustra fizycznie, jest spowolniony, ale nie zniszczony -- "
"więcej odbić wyjdzie z lustra. Użyj Mimików, by go zniszczyć.")
// peaceful texts
S("memory game", "gra pamięciowa")
S("display hints", "pokaż wskazówki")
S("hyperbolic puzzles", "hiperboliczne zagadki")
// missing descriptions
S( "A strange land filled with mirrors. "
"Break magic mirrors and enter clouds of mirage to "
"gain treasures and helpful Mimics.",
"Dziwna kraina wypełniona lustrami. "
"Rozbijaj magiczne lustra i wchodź w chmury mirażowe, "
"by zdobywać skarby i przyjazne Mimiki.")
S(
"A perfect mirror wall. It is unbreakable "
"and impassable "
"even for aethereal beings, and everything "
"you see inside is just an image of "
"the real world; you can swing your sword "
"at them, but that will not destroy them "
"in the real world. "
"Mirror walls reflect Mimics, lightning bolts, and "
"missiles perfectly.",
"Doskonała lustrzana ściana. Nie da się jej zniszczyć, "
"i nawet istoty eteryczne nie są w stanie "
"przejść na drugą stronę. Wszystko co widzisz "
"jest tylko obrazem świata rzeczywistego; "
"możesz machnąć mieczem w kierunku tego obrazu, "
"ale to nie wpłynier na rzeczywistość. "
"Lustrzany ściany perfekcyjnie odbijają Mimiki, "
"błyskawice, i pociski."
)
S(
"In the peaceful mode, you just explore the world, "
"without any battles; there are also several "
"navigational puzzles available. In the memory game, "
"you have to collect as many Dodecahedra as you can, "
"and return to the starting point -- hyperbolic geometry "
"makes this extremely difficult! Other hyperbolic puzzles "
"include the Burial Grounds (excavate the treasures "
"using your magical sword), Galápagos (try to find an adult "
"tortoise matching the baby), Camelot (find the center of "
"a large hyperbolic circle), and Palace (follow the mouse). "
"Other places listed are for exploration.",
"W trybie spokojnym zwiedzasz świat bez żadnej walki; "
"jest też tu kilka hiperbolicznych zagadek nawigacyjnych. "
"W grze pamięciowej musisz zebrać jak najwięcej Dwunastościanów "
"i wrócić do punktu wyjścia -- geometria hiperboliczna powoduje, "
"że jest to bardzo trudne! Pozostałe zagadki to Kurhany "
"(wykopuj skarby swoim magicznym mieczem), Galapágos "
"(znajdź dużego żółwia odpowiadającego żółwiątku), "
"Camelot (znajdź środek wielkiego hiperbolicznego kółka), "
"i Pałac (idź za myszą). Można też zwiedzić kilka "
"innych miejsc.")
S("puzzles and exploration", "hádanky a zkoumání")
#undef Orb

View File

@ -347,7 +347,7 @@ S("Hyperstone Quest: collect at least %3 %1 in %the2", "Миссия Гипер
S("Hyperstone Quest completed!", "Миссия Гиперкамня закончена!")
S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Ищите сферы Йендора в Аду и на Перекрёстке!")
S("Unlock the Orb of Yendor!", "Откройте сферу Йендора!")
S("Defeat 100 enemies to access the Graveyard", "Убейте 100 врагов, чтобы открыть Кладбище")
S("Defeat %1 enemies to access the Graveyard", "Убейте %1 врагов, чтобы открыть Кладбище")
S("(press ESC during the game to review your quest)", "(нажмите ESC во время игры, чтобы посмотреть ваши миссии)")
S("you have cheated %1 times", "количество читов: %1")
S("%1 turns (%2)", "ходов: %1 (%2)")
@ -5263,7 +5263,7 @@ S("The game starts in the Icy Lands. Collect the Ice Diamonds "
S("Hypersian Rug model", "Модель Гиперсидского ковра")
S(
"New players think that the action of HyperRogue takes place on a sphere. "
#ifdef MOBWEB
#if ISMOBWEB
"This is not true -- the Tutorial in the native desktop version shows "
"the surface HyperRogue actually takes place on.",
#else
@ -5274,7 +5274,7 @@ S(
#endif
"Новички иногда думают, что действие в HyperRogue происходит на сфере. "
#ifdef MOBWEB
#if ISMOBWEB
"Это неправда -- Руководство в компьютерной версии покажет тебе "
"настоящую поверхность HyperRogue."
#else
@ -5360,7 +5360,7 @@ S(
"it will appear to go slower -- this is because you are running "
"in a straight line, and the Running Dog has to run in a curve "
"called an equidistant.\n\n"
#ifdef MAC
#if ISMAC
"Remember that you can click with right Shift on anything to get more information.",
#else
"Remember that you can right click on anything to get more information.",

View File

@ -328,7 +328,7 @@ S("Hyperstone Quest: collect at least %3 %1 in %the2", "Aşkıntaş Görevi: %2'
S("Hyperstone Quest completed!", "Aşkıntaş görevi tamamlandı.")
S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Yendorun Küreleri için Cehennemi yahut Arayolları ara!")
S("Unlock the Orb of Yendor!", "Yendor'un küresinin kilidini aç!")
S("Defeat 100 enemies to access the Graveyard", "Mezarlığa erişmek için 100 düşman öldür.")
S("Defeat %1 enemies to access the Graveyard", "Mezarlığa erişmek için %1 düşman öldür.")
S("(press ESC during the game to review your quest)", "(Görevine bakmak için oyun sırasında ESC'ye bas.)")
S("you have cheated %1 times", "şimdiye kadar %1 kez hile yaptın.")
S("%1 turns (%2)", "tur sayısı: %1 (%2)")

View File

@ -57,7 +57,7 @@ struct fullnoun {
const char* natchars[NUMEXTRA] = {"°","é","á"};
#endif
#ifndef NOTRANS
#if CAP_TRANS
#include "language-data.cpp"
hashcode langhash(const string& s) {
@ -107,7 +107,7 @@ set<string> warnshown;
void basicrep(string& x) {
#ifndef NOTRANS
#if CAP_TRANS
const sentence *s = findInHashTable(x, all_sentences);
if(!s && !warnshown.count(x)) {
printf("WARNING: no translations for '%s'\n", x.c_str());
@ -134,7 +134,7 @@ void basicrep(string& x) {
}
void parrep(string& x, string w, stringpar p) {
#ifndef NOTRANS
#if CAP_TRANS
int l = lang();
const fullnoun *N = findInHashTable(p.v, all_nouns);
if(l == 1) {
@ -326,7 +326,7 @@ string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4, st
string XLATN(string x) {
#ifndef NOTRANS
#if CAP_TRANS
if(lang()) {
const fullnoun *N = findInHashTable(x, all_nouns);
if(N) return N->n[lang()-1].nomp;
@ -336,7 +336,7 @@ string XLATN(string x) {
}
string XLAT1(string x) {
#ifndef NOTRANS
#if CAP_TRANS
if(lang()) {
const fullnoun *N = findInHashTable(x, all_nouns);
if(N) return N->n[lang()-1].nom;

View File

@ -4,7 +4,7 @@
#include <map>
#include <stdint.h>
#ifdef WINDOWS
#if ISWINDOWS
#include "direntx.h"
#include "direntx.c"
#else
@ -23,7 +23,7 @@ namespace mapeditor {
} ew, ewsearch;
bool autochoose;
#ifndef NOEDIT
#if CAP_EDIT
map<int, cell*> modelcell;
void handleKeyMap(int sym, int uni);
@ -49,7 +49,7 @@ namespace mapeditor {
#endif
}
#ifndef NOEDIT
#if CAP_EDIT
namespace mapstream {
std::map<cell*, int> cellids;
vector<cell*> cellbyid;
@ -425,7 +425,7 @@ namespace mapeditor {
cell *drawcell;
#ifndef NOEDIT
#if CAP_EDIT
int paintwhat = 0;
int painttype = 0;
int radius = 0;
@ -1173,12 +1173,16 @@ namespace mapeditor {
cfileext = ".lev";
pushScreen(drawFileDialog);
}
#if CAP_SDL
else if(sym == SDLK_F6) {
saveHighQualityShot();
}
#endif
#if CAP_SVG
else if(sym == SDLK_F8) {
svg::render();
}
#endif
else if(sym == SDLK_F7) {
drawplayer = !drawplayer;
}
@ -1691,10 +1695,12 @@ namespace mapeditor {
if(sym == SDLK_F7) {
drawplayer = !drawplayer;
}
#if CAP_SDL
if(sym == SDLK_F6) {
saveHighQualityShot();
}
#endif
if(sym == SDLK_F8) {
svg::render();
@ -1867,7 +1873,7 @@ namespace mapeditor {
}
bool drawUserShape(transmatrix V, int group, int id, int color, cell *c) {
#ifdef MOBILE
#if ISMOBILE==1
return false;
#else
@ -1882,7 +1888,7 @@ namespace mapeditor {
}
}
#ifndef NOEDIT
#if CAP_EDIT
if((cmode & sm::DRAW) && mapeditor::editingShape(group, id)) {
/* for(int a=0; a<size(ds.list); a++) {

View File

@ -17,6 +17,7 @@ int PREC(ld x) {
}
void showOverview() {
cmode = sm::ZOOMABLE | sm::OVERVIEW;
DEBB(DF_GRAPH, (debugfile,"show overview\n"));
mouseovers = XLAT("world overview");
mouseovers += " ";
@ -175,7 +176,7 @@ void showMainMenu() {
dialog::addItem(XLAT("special display modes"), 'd');
dialog::addItem(XLAT("special game modes"), 'm');
#ifndef NOSAVE
#if CAP_SAVE
dialog::addItem(XLAT("local highscores"), 't');
#endif
dialog::addItem(XLAT("help"), 'h'); dialog::lastItem().keycaption += " / F1";
@ -185,7 +186,7 @@ void showMainMenu() {
dialog::addItem(XLAT("restart game"), 'r'); dialog::lastItem().keycaption += " / F5";
string q;
#ifdef MOBILE
#if ISMOBILE==1
dialog::addItem(XLAT("visit the website"), 'q');
#else
q = quitsaves() ? "save" : "quit";
@ -203,17 +204,17 @@ void showMainMenu() {
if(inv::on)
dialog::addItem(XLAT("inventory"), 'i');
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
dialog::addItem(XLAT("rogueviz menu"), 'u');
#endif
#ifdef MOBILE
#if ISMOBILE==1
#ifdef HAVE_ACHIEVEMENTS
dialog::addItem(XLAT("leaderboards/achievements"), '3');
#endif
#endif
#ifdef ANDROIDSHARE
#if CAP_ANDROIDSHARE
dialog::addItem("SHARE", 's'-96);
#endif
@ -232,20 +233,25 @@ void showMainMenu() {
else if(sym == 'g') pushScreen(showGraphConfig);
else if(sym == 'd') pushScreen(showDisplayMode);
else if(sym == 'm') pushScreen(showChangeMode);
#ifndef NOSAVE
#if CAP_SAVE
else if(sym == 't') scores::load();
#endif
else if(sym == 'r' || sym == SDLK_F5) {
restartGame();
popScreen();
}
else if(sym == 'q' || sym == SDLK_F10)
else if(sym == 'q' || sym == SDLK_F10) {
#if ISMOBILE
extern void openURL();
openURL();
#else
quitmainloop = true;
#endif
}
else if(sym == 'o') {
clearMessages();
pushScreen(showOverview);
setAppropriateOverview();
}
#ifdef INV
#if CAP_INV
else if(sym == 'i') {
clearMessages();
pushScreen(inv::show);
@ -253,7 +259,7 @@ void showMainMenu() {
#endif
else if(sym == SDLK_ESCAPE)
showMissionScreen();
#ifdef MOBILE
#if ISMOBILE==1
#ifdef HAVE_ACHIEVEMENTS
else if(sym == '3') {
achievement_final(false);
@ -261,7 +267,7 @@ void showMainMenu() {
}
#endif
#endif
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
else if(uni == 'u') pushScreen(rogueviz::showMenu);
#endif
else if(doexiton(sym, uni)) {
@ -299,15 +305,15 @@ void showDisplayMode() {
dialog::addBreak(50);
#ifndef NOEDIT
#if CAP_EDIT
dialog::addBoolItem(XLAT("vector graphics editor"), (false), 'g');
#endif
// display modes
#ifndef NORUG
#if CAP_RUG
dialog::addBoolItem(XLAT("hypersian rug mode"), (rug::rugged), 'u');
#endif
#ifndef NOMODEL
#if CAP_MODEL
dialog::addBoolItem(XLAT("paper model creator"), (false), 'n');
#endif
dialog::addBoolItem(XLAT("conformal/history mode"), (conformal::on), 'a');
@ -333,7 +339,7 @@ void showDisplayMode() {
if(xuni == '9') pushScreen(show3D);
#ifndef NOEDIT
#if CAP_EDIT
else if(xuni == 'g') {
pushScreen(mapeditor::showDrawEditor);
mapeditor::initdraw(cwt.c);
@ -343,7 +349,7 @@ void showDisplayMode() {
else if(xuni == 'x') {
viewdists = !viewdists;
}
#ifndef NORUG
#if CAP_RUG
else if(xuni == 'u') {
if(sphere) projectionDialog();
else rug::select();
@ -352,7 +358,7 @@ void showDisplayMode() {
else if(uni == 'a')
pushScreen(conformal::show);
#ifndef NOMODEL
#if CAP_MODEL
else if(xuni == 'n')
pushScreen(netgen::show);
#endif
@ -369,7 +375,6 @@ void switchHardcore() {
if(hardcore && !canmove) {
restartGame();
hardcore = false;
popScreen();
}
else if(hardcore && canmove) { hardcore = false; }
else { hardcore = true; canmove = true; hardcoreAt = turncount; }
@ -377,7 +382,7 @@ void switchHardcore() {
addMessage("One wrong move, and it is game over!");
else
addMessage("Not so hardcore?");
if(pureHardcore()) popScreen();
if(pureHardcore()) popScreenAll();
}
void showChangeMode() {
@ -386,7 +391,7 @@ void showChangeMode() {
// gameplay modes
#ifdef TOUR
#if CAP_TOUR
dialog::addBoolItem(XLAT("Tutorial"), tour::on, 'T');
#endif
@ -400,7 +405,7 @@ void showChangeMode() {
multi::cpid = 0;
dialog::addBoolItem(XLAT("heptagonal mode"), (purehepta), '7');
dialog::addBoolItem(XLAT("Chaos mode"), (chaosmode), 'C');
dialog::addBoolItem(XLAT("peaceful mode"), (chaosmode), 'p');
dialog::addBoolItem(XLAT("peaceful mode"), peace::on, 'p');
dialog::addBoolItem(XLAT("Orb Strategy mode"), (inv::on), 'i');
dialog::addBoolItem(XLAT("pure tactics mode"), (tactic::on), 't');
dialog::addBoolItem(XLAT("Yendor Challenge"), (yendor::on), 'y');
@ -411,7 +416,7 @@ void showChangeMode() {
// cheating and map editor
dialog::addBoolItem(XLAT("cheat mode"), (cheater), 'c');
#ifndef NOEDIT
#if CAP_EDIT
dialog::addBoolItem(XLAT("map editor"), (false), 'm');
#endif
@ -433,7 +438,7 @@ void showChangeMode() {
else if(!cheater) {
cheater++;
addMessage(XLAT("You activate your demonic powers!"));
#ifndef MOBILE
#if ISMOBILE==0
addMessage(XLAT("Shift+F, Shift+O, Shift+T, Shift+L, Shift+U, etc."));
#endif
popScreen();
@ -464,7 +469,7 @@ void showChangeMode() {
else if(xuni == 'i') {
restartGame('i');
}
#ifdef TOUR
#if CAP_TOUR
else if(uni == 'T') {
tour::start();
}
@ -484,7 +489,7 @@ void showChangeMode() {
else
restartGame('P');
}
#ifndef NOEDIT
#if CAP_EDIT
else if(xuni == 'm') {
if(tactic::on)
addMessage(XLAT("Not available in the pure tactics mode!"));
@ -497,7 +502,7 @@ void showChangeMode() {
}
#endif
else if(xuni == 's') {
#ifdef MOBILE
#if ISMOBILE==1
restartGame('s');
#else
multi::shmupcfg = shmup::on;
@ -592,7 +597,7 @@ void showEuclideanMenu() {
if(hiitemsMax(treasureType(eLand(i))) >= 25) landvisited[i] = true;
landvisited[laCrossroads] = true;
landvisited[laIce] = true;
landvisited[laMirror] = true;
landvisited[laMirrorOld] = true;
landvisited[laPrincessQuest] = cheater || princess::everSaved;
landvisited[laWildWest] = true;
landvisited[laHalloween] = true;
@ -638,7 +643,6 @@ void showEuclideanMenu() {
if(uni == '0') {
targetgeometry = geometry;
restartGame('g');
popScreen();
}
else if(uni == '5') {
targetgeometry = eGeometry(1+targetgeometry);
@ -657,7 +661,6 @@ void showEuclideanMenu() {
restartGame(tactic::on ? 't' : 0);
// disable PTM if chosen a land from the Euclidean menu
if(tactic::on) restartGame('t');
popScreen();
}
else euclidland = laIce;
}
@ -735,31 +738,26 @@ void handleDemoKey(int sym, int uni) {
firstland = laIce;
if(tactic::on) restartGame('t');
else restartGame();
popScreen();
}
else if(sym == 'T') {
firstland = laIce;
if(!tour::on) tour::start();
popScreen();
}
else if(sym == 't') {
firstland = laTemple;
if(!tactic::on) restartGame('t');
else restartGame();
popScreen();
}
else if(sym == 'l') {
firstland = laStorms;
if(!tactic::on) restartGame('t');
else restartGame();
popScreen();
}
else if(sym == 'b') {
firstland = laBurial;
if(!tactic::on) restartGame('t');
else restartGame();
items[itOrbSword] = 60;
popScreen();
}
}
#endif

View File

@ -1,7 +1,7 @@
// HyperRogue paper model generator
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
#ifndef NOMODEL
#if CAP_MODEL
namespace netgen {
// We need a two-dimensional vector class for this.
@ -214,13 +214,13 @@ namespace netgen {
//============================
void blackline(vec v1, vec v2, int col = 0x000000FF) {
#ifdef GFX
#if CAP_SDLGFX==1
aalineColor(s, int(v1.x), int(v1.y), int(v2.x), int(v2.y), col);
#endif
}
void drawtriangle(vec v1, vec v2, vec v3, int col) {
#ifdef GFX
#if CAP_SDLGFX==1
polyx[0] = int(v1.x);
polyx[1] = int(v2.x);
polyx[2] = int(v3.x);
@ -232,7 +232,7 @@ namespace netgen {
}
void blackcircle(vec v, int r, int col = 0x000000FF) {
#ifdef GFX
#if CAP_SDLGFX
aacircleColor(s, int(v.x), int(v.y), r, col);
#endif
}
@ -297,7 +297,7 @@ namespace netgen {
// draw the model
void createPapermodel() {
#ifndef GFX
#if !CAP_SDLGFX
addMessage(XLAT("High quality shots not available on this platform"));
return;
#endif

View File

@ -1,4 +1,4 @@
#ifdef NOTTF
#if CAP_TABFONT
unsigned char fonttable[] = {
43,13,0,255,0,255,0,49,
43,16,0,133,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,236,255,4,235,0,10,206,255,4,205,0,10,176,255,4,175,0,10,146,255,4,145,0,10,116,255,4,115,0,10,86,255,4,85,0,10,55,255,4,55,0,58,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,149,
@ -254,7 +254,7 @@ void loadCompressedChar(int &otwidth, int &otheight, int *tpix) {
}
#endif
#ifdef CREATEFONT
#if CAP_CREATEFONT
void generateFont(int ch, SDL_Surface *txt) {
if(ch >= 32) {
printf("%d,%d,", txt->h, txt->w);

View File

@ -443,18 +443,14 @@ void castLightningBolt(cellwalker lig) {
cwspin(lig, 3);
if(c->type == 7) cwspin(lig, hrand(2));
}
if(c->wall == waCloud) {
drawParticles(c, winf[ow].color, 16);
c->wall = waNone;
mirror::createMirages(c, lig.spin, moLightningBolt);
if(lig.c->wall == waCloud) {
lig.c->wall = waNone;
mirror::createMirages(lig, mirror::LIGHTNING);
}
if(c->wall == waMirror) {
drawParticles(c, winf[ow].color, 16);
c->wall = waNone;
mirror::createMirrors(c, lig.spin, moLightningBolt);
break;
if(lig.c->wall == waMirror) {
lig.c->wall = waNone;
mirror::createMirrors(lig, mirror::LIGHTNING);
}
}
}
@ -542,7 +538,7 @@ void teleportTo(cell *dest) {
drainOrb(itOrbTeleport);
addMessage(XLAT("You teleport to a new location!"));
mirror::destroy();
mirror::destroyAll();
for(int i=9; i>=0; i--)
setdist(cwt.c, i, NULL);
@ -589,7 +585,7 @@ void jumpTo(cell *dest, eItem byWhat, int bonuskill = 0, eMonster dashmon = moNo
addMessage(XLAT("You vault over %the1!", dashmon));
}
mirror::destroy();
mirror::destroyAll();
for(int i=9; i>=0; i--)
setdist(cwt.c, i, NULL);

View File

@ -68,7 +68,7 @@ struct polytodraw {
qchr chr;
qcir cir;
} u;
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
string* info;
polytodraw() { info = NULL; }
#endif
@ -123,16 +123,43 @@ void shift(hpcshape& sh, double dx, double dy, double dz) {
hpc[i] = m * hpc[i];
}
#ifndef MOBILE
#if ISMOBILE==0
SDL_Surface *aux;
#endif
vector<polytodraw*> ptds2;
#define CAP_POLY (CAP_SDLGFX || CAP_GL || CAP_SVG)
#if CAP_POLY
vector<polytodraw*> ptds2;
#define POLYMAX 60000
#ifdef GL
#define USEPOLY
#if CAP_GL
GLfloat *currentvertices;
#endif
GLfloat *ourshape = NULL;
void initPolyForGL() {
if(ourshape) delete[] ourshape;
ourshape = new GLfloat[3 * qhpc];
// GLfloat ourshape[3*qhpc];
int id = 0;
for(int i=0; i<qhpc; i++) {
ourshape[id++] = hpc[i][0];
ourshape[id++] = hpc[i][1];
ourshape[id++] = hpc[i][2];
}
#if CAP_GL
currentvertices = NULL;
#endif
}
#endif
#if CAP_GL
GLuint shapebuffer;
@ -141,7 +168,6 @@ int qglcoords;
extern void glcolor(int color);
GLfloat *currentvertices;
void activateVertexArray(GLfloat *f, int qty) {
currentvertices = f;
@ -162,34 +188,6 @@ void activateGlcoords() {
}
#endif
#ifdef GFX
#define POLYMAX 60000
#define USEPOLY
#endif
#ifdef USEPOLY
GLfloat *ourshape = NULL;
void initPolyForGL() {
if(ourshape) delete[] ourshape;
ourshape = new GLfloat[3 * qhpc];
// GLfloat ourshape[3*qhpc];
int id = 0;
for(int i=0; i<qhpc; i++) {
ourshape[id++] = hpc[i][0];
ourshape[id++] = hpc[i][1];
ourshape[id++] = hpc[i][2];
}
#ifdef GL
currentvertices = NULL;
#endif
}
#endif
int polyi;
int polyx[POLYMAX], polyxr[POLYMAX], polyy[POLYMAX];
@ -201,7 +199,7 @@ hyperpoint gltopoint(GLfloat t[3]) {
}
void addpoint(const hyperpoint& H) {
#ifdef GL
#if CAP_GL
if(vid.usingGL) {
if(polyi >= POLYMAX) return;
if(pmodel) {
@ -254,7 +252,7 @@ void addpoly(const transmatrix& V, GLfloat *tab, int cnt) {
}
}
#ifdef SDLGFX
#if CAP_SDLGFX
void aapolylineColor(SDL_Surface *s, int*x, int *y, int polyi, int col) {
for(int i=1; i<polyi; i++)
aalineColor(s, x[i-1], y[i-1], x[i], y[i], col);
@ -272,7 +270,7 @@ void filledPolygonColorI(SDL_Surface *s, int* polyx, int *polyy, int polyi, int
}
#endif
#ifdef GL
#if CAP_GL
void glcolor2(int color) {
unsigned char *c = (unsigned char*) (&color);
glColor4f(c[3] / 255.0, c[2] / 255.0, c[1]/255.0, c[0] / 255.0);
@ -373,7 +371,7 @@ double linewidthat(const hyperpoint& h) {
}
void drawpolyline(const transmatrix& V, GLfloat* tab, int cnt, int col, int outline) {
#ifdef GL
#if CAP_GL
if(vid.usingGL) {
if(pmodel == mdDisk) {
const int pq = cnt;
@ -396,28 +394,17 @@ void drawpolyline(const transmatrix& V, GLfloat* tab, int cnt, int col, int outl
polyi = 0;
addpoly(V, tab, cnt);
#ifdef MOBILE
#ifdef ANDROID
#define ANDROIDGD
#if CAP_SVG==1
if(svg::in) {
svg::polygon(polyx, polyy, polyi, col, outline);
return;
}
#endif
#ifdef FAKEMOBILE
#define ANDROIDGD
#endif
#ifdef ANDROIDGD
#if CAP_XGD==1
gdpush(1); gdpush(col); gdpush(outline); gdpush(polyi);
for(int i=0; i<polyi; i++) gdpush(polyx[i]), gdpush(polyy[i]);
#endif
#else
#ifndef MOBILE
if(svg::in) svg::polygon(polyx, polyy, polyi, col, outline);
#endif
#ifdef SDLGFX
#elif CAP_SDLGFX==1
filledPolygonColorI(s, polyx, polyy, polyi, col);
if(vid.goteyes) filledPolygonColorI(aux, polyxr, polyy, polyi, col);
@ -434,7 +421,6 @@ void drawpolyline(const transmatrix& V, GLfloat* tab, int cnt, int col, int outl
for(int t=0; t<polyi; t++) polyx[t] -= x, polyy[t] -= y;
}
}
#endif
#endif
}
@ -464,7 +450,7 @@ vector<GLfloat> curvedata;
int curvestart = 0;
void drawqueueitem(polytodraw& ptd) {
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
svg::info = ptd.info;
#endif
@ -486,7 +472,7 @@ void drawqueueitem(polytodraw& ptd) {
}
else if(ptd.kind == pkString) {
qchr& q(ptd.u.chr);
#ifndef MOBILE
#if ISMOBILE==0
if(svg::in)
svg::text(q.x, q.y, q.size, q.str, q.frame, ptd.col, q.align);
else {
@ -498,7 +484,7 @@ void drawqueueitem(polytodraw& ptd) {
#endif
}
else if(ptd.kind == pkCircle) {
#ifndef MOBILE
#if ISMOBILE==0
if(svg::in)
svg::circle(ptd.u.cir.x, ptd.u.cir.y, ptd.u.cir.size, ptd.col);
else
@ -506,7 +492,7 @@ void drawqueueitem(polytodraw& ptd) {
drawCircle(ptd.u.cir.x, ptd.u.cir.y, ptd.u.cir.size, ptd.col);
}
#ifndef NOSDL
#if CAP_SDL
if(vid.goteyes && !vid.usingGL) {
int qty = s->w * s->h;
int *a = (int*) s->pixels;
@ -533,13 +519,12 @@ void quickqueue() {
}
void drawqueue() {
#ifdef USEPOLY
int siz = size(ptds);
setcameraangle(true);
#ifdef GL
#if CAP_GL
if(vid.usingGL)
glClear(GL_STENCIL_BUFFER_BIT);
#endif
@ -574,7 +559,7 @@ void drawqueue() {
#endif
profile_stop(3);
#ifndef NOSDL
#if CAP_SDL
if(vid.goteyes && !vid.usingGL) {
if(aux && (aux->w != s->w || aux->h != s->h))
@ -600,13 +585,12 @@ void drawqueue() {
drawqueueitem(ptd);
}
#ifdef GL
#if CAP_GL
if(vid.goteyes && vid.usingGL) selectEyeGL(0), selectEyeMask(0);
#endif
setcameraangle(false);
curvedata.clear(); curvestart = 0;
#endif
}
hpcshape
@ -1814,13 +1798,13 @@ void queuecircle(int x, int y, int size, int color, int prio = PPR_CIRCLE) {
ptd.prio = prio << PSHIFT;
}
#ifdef MOBILE
#if ISMOBILE==1
namespace svg {
bool in = false;
}
#endif
#ifndef MOBILE
#if ISMOBILE==0
// svg renderer
namespace svg {
FILE *f;
@ -1989,7 +1973,7 @@ namespace svg {
vid.usingGL = false;
vid.xres = vid.yres = svgsize ? svgsize : min(1 << (sightrange+7), 16384);
calcparam();
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::fixparam();
#endif
inHighQual = true;

View File

@ -64,7 +64,7 @@ hint hints[] = {
[]() {
dialog::addHelp(XLAT(
"Remember that you can right click mostly anything for more information."));
#ifdef MAC
#if ISMAC
dialog::addHelp(XLAT(
"(You can also use right Shift)\n\n"));
#endif
@ -73,7 +73,7 @@ hint hints[] = {
{
0,
[]() { return !canmove; },
[]() { return !canmove; },
[]() {
dialog::addHelp(XLAT(
"Want to understand the geometry in HyperRogue? Try the Tutorial!"
@ -82,7 +82,11 @@ hint hints[] = {
dialog::addItem(XLAT("Tutorial"), 'z');
},
[]() {
#if CAP_TOUR
tour::start();
#else
addMessage("Not in this version");
#endif
}},
{
@ -104,16 +108,14 @@ hint hints[] = {
"Press ESC to view this screen during the game."
));
},
[]() {
tour::start();
}},
noaction
},
{
0,
[]() { return true; },
[]() {
dialog::addInfo(XLAT(
#ifdef MOBILE
#if ISMOBILE==1
"The 'world overview' shows all the lands in HyperRogue."
#else
"Press 'o' to see all the lands in HyperRogue."
@ -170,14 +172,14 @@ hint hints[] = {
#endif
},
[]() {
#ifdef INV
#if CAP_INV
restartGame('i');
#endif
}
},
{
0,
[]() { return geometry == gNormal; },
[]() { return CAP_RUG && geometry == gNormal; },
[]() {
dialog::addHelp(XLAT(
"Do you think you are playing on a ball? "
@ -187,6 +189,7 @@ hint hints[] = {
dialog::addItem(XLAT("hypersian rug mode"), 'z');
},
[] () {
#if CAP_RUG
popScreen();
int wm, mm;
rug::init();
@ -199,6 +202,7 @@ hint hints[] = {
vid.wallmode = wm;
vid.monmode = mm;
};
#endif
}
},
@ -274,13 +278,11 @@ hint hints[] = {
restartGame('E');
vid.alpha = 999;
vid.scale = 998;
popScreen();
}
else {
restartGame('E');
vid.alpha = 1;
vid.scale = 1;
popScreen();
}
}
},
@ -301,7 +303,7 @@ void showMission() {
keyhandler = handleKeyQuit;
dialog::init(
#ifdef TOUR
#if CAP_TOUR
tour::on ? (canmove ? XLAT("Tutorial") : XLAT("GAME OVER")) :
#endif
cheater ? XLAT("It is a shame to cheat!") :
@ -314,7 +316,7 @@ void showMission() {
dialog::addInfo(XLAT("Your score: %1", its(gold())));
dialog::addInfo(XLAT("Enemies killed: %1", its(tkills())));
#ifdef TOUR
#if CAP_TOUR
if(tour::on) ; else
#endif
if(items[itOrbYendor]) {
@ -346,7 +348,7 @@ void showMission() {
timerstart = time(NULL);
if(princess::challenge) ;
#ifdef TOUR
#if CAP_TOUR
else if(tour::on) ;
#endif
else if(tkills() < R100)
@ -394,20 +396,22 @@ void showMission() {
}
dialog::addBreak(100);
#if CAP_TOUR
if(!tour::on) {
hints[hinttoshow].display();
dialog::addBreak(100);
}
#endif
bool intour = false;
#ifdef TOUR
#if CAP_TOUR
intour = tour::on;
#endif
if(intour) {
#ifdef TOUR
#if CAP_TOUR
if(canmove) {
dialog::addItem(XLAT("spherical geometry"), '1');
dialog::addItem(XLAT("Euclidean geometry"), '2');
@ -439,10 +443,10 @@ void showMission() {
dialog::addItem(XLAT("restart"), SDLK_F5);
if(inv::on && items[itInventory])
dialog::addItem(XLAT("inventory"), 'i');
#ifndef MOBILE
#if ISMOBILE==0
dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10);
#endif
#ifdef ANDROIDSHARE
#if CAP_ANDROIDSHARE
dialog::addItem(XLAT("SHARE"), 's'-96);
#endif
dialog::addBreak(500);
@ -458,7 +462,7 @@ void handleKeyQuit(int sym, int uni) {
dialog::handleNavigation(sym, uni);
// ignore the camera movement keys
#ifndef NORUG
#if CAP_RUG
if(rug::rugged && (sym == SDLK_UP || sym == SDLK_DOWN || sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN ||
sym == SDLK_RIGHT || sym == SDLK_LEFT))
sym = 0;
@ -478,11 +482,11 @@ void handleKeyQuit(int sym, int uni) {
else if(sym == SDLK_F3 || (sym == ' ' || sym == SDLK_HOME))
fullcenter();
else if(uni == 'o') setAppropriateOverview();
#ifdef INV
#if CAP_INV
else if(uni == 'i' && inv::on)
pushScreen(inv::show);
#endif
#ifndef NOSAVE
#if CAP_SAVE
else if(uni == 't') {
msgs.clear();
scores::load();
@ -511,7 +515,10 @@ void showMissionScreen() {
achievement_final(false);
msgscroll = 0;
if(!tour::on) {
#if CAP_TOUR
if(!tour::on)
#endif
{
int ch = counthints();
hinttoshow = ch;
int h;

View File

@ -595,7 +595,7 @@ namespace sag {
return cost;
}
MTRand53 los;
mt19937 los;
bool infullsa;
@ -1256,7 +1256,7 @@ void drawExtra() {
canmove = true; items[itOrbAether] = true;
}
#ifndef NORUG
#if CAP_RUG
if(!rug::rugged)
#endif
for(int i=0; i<size(legend); i++) {
@ -1341,7 +1341,7 @@ void readcolor(const char *cfname) {
void init() {
if(on) return;
autocheat = true;
#ifndef WEB
#if !ISWEB
mapeditor::drawplayer = false;
firstland = euclidland = laCanvas;
if(!shmup::on) restartGame('s');
@ -1385,7 +1385,7 @@ void fixparam() {
if(size(legend)) vid.xcenter = vid.ycenter;
}
#ifndef NOSDL
#if CAP_SDL
void rvvideo(const char *fname) {
if(kind == kCollatz) {
pngformat = 2;
@ -1713,7 +1713,7 @@ int readArgs() {
else if(argis("-TURN")) {
PHASE(3); shmup::turn(100);
}
#ifndef NOSDL
#if CAP_SDL
else if(argis("-video")) {
shift(); rvvideo(args());
}

20
rug.cpp
View File

@ -3,13 +3,13 @@
// implementation of the Hypersian Rug mode
#ifndef NORUG
#if CAP_RUG
#define TEXTURESIZE (texturesize)
#define HTEXTURESIZE (texturesize/2)
#ifdef AVOID_GLEW
#ifdef LINUX
#if !CAP_GLEW
#if ISLINUX
extern "C" {
GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
@ -25,7 +25,7 @@ GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers)
}
#endif
#ifdef MAC
#if ISMAC
#define glFramebufferTexture glFramebufferTextureEXT
#endif
#endif
@ -380,7 +380,7 @@ Uint32 *expanded_data;
void initTexture() {
if(!rendernogl) {
#ifndef PANDORA
#if !ISPANDORA
FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
@ -440,7 +440,7 @@ void prepareTexture() {
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TEXTURESIZE, TEXTURESIZE, 0, GL_BGRA, GL_UNSIGNED_BYTE, expanded_data );
}
else {
#ifndef PANDORA
#if !ISPANDORA
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glViewport(0,0,TEXTURESIZE,TEXTURESIZE);
@ -463,7 +463,7 @@ void closeTexture() {
delete[] expanded_data;
}
else {
#ifndef PANDORA
#if !ISPANDORA
glDeleteTextures(1, &renderedTexture);
glDeleteRenderbuffers(1, &depth_stencil_rb);
glDeleteFramebuffers(1, &FramebufferName);
@ -569,7 +569,7 @@ transmatrix rotmatrix(double rotation, int c0, int c1) {
transmatrix currentrot;
void init() {
#ifndef AVOID_GLEW
#if CAP_GLEW
if(!glew) {
glew = true;
GLenum err = glewInit();
@ -668,7 +668,7 @@ void show() {
dialog::addSelItem(XLAT("texture size"), its(texturesize)+"x"+its(texturesize), 's');
dialog::display();
keyhandler = [] (int sym, int uni) {
#ifdef PANDORA
#if ISPANDORA
rendernogl = true;
#endif
dialog::handleNavigation(sym, uni);
@ -690,7 +690,7 @@ void show() {
}
else if(uni == 'o')
renderonce = !renderonce;
#ifndef PANDORA
#if !ISPANDORA
else if(uni == 'g')
rendernogl = !rendernogl;
#endif

View File

@ -1,4 +1,4 @@
#ifndef NOSAVE
#if CAP_SAVE
namespace scores {

263
shmup.cpp
View File

@ -134,7 +134,7 @@ char* axeconfigs[24]; int numaxeconfigs;
int* dzconfigs[24];
string listkeys(int id) {
#ifndef NOSDL
#if CAP_SDL
string lk = "";
for(int i=0; i<512; i++)
if(vid.scfg.keyaction[i] == id)
@ -149,8 +149,7 @@ string listkeys(int id) {
lk = lk + " " + cts('A'+i)+"-"+"URDL"[d];
}
return lk;
#endif
#ifdef NOSDL
#else
return "";
#endif
}
@ -179,7 +178,7 @@ bool configdead;
void handleConfig(int sym, int uni);
void showShmupConfig() {
#ifndef NOSDL
#if CAP_SDL
cmode = sm::SHMUPCONFIG;
int sc = vid.scfg.subconfig;
@ -287,7 +286,7 @@ void showShmupConfig() {
dialog::addBreak(50);
#ifndef NOCONFIG
#if CAP_CONFIG
dialog::addItem(XLAT("save the configuration"), 'c');
#endif
@ -332,7 +331,7 @@ void showShmupConfig() {
}
void handleConfig(int sym, int uni) {
#ifndef NOSDL
#if CAP_SDL
if(!vid.scfg.setwhat) dialog::handleNavigation(sym, uni);
int sc = vid.scfg.subconfig;
if(sc == 0) {
@ -352,7 +351,7 @@ void handleConfig(int sym, int uni) {
kills[i] = deaths[i] = treasures[i] = 0;
else if(uni == 's' || uni == 't')
shmupcfg = !shmupcfg;
#ifndef NOCONFIG
#if CAP_CONFIG
else if(uni == 'c')
::saveConfig();
#endif
@ -462,7 +461,7 @@ bool notremapped(int sym) {
return k > multi::players;
}
#ifndef NOCONFIG
#if CAP_CONFIG
void initConfig() {
vid.scfg.players = 1;
@ -474,7 +473,7 @@ void initConfig() {
t['s'] = 16 + 6;
t['a'] = 16 + 7;
#ifndef MOBILE
#if ISMOBILE==0
t[SDLK_KP8] = 16 + 4;
t[SDLK_KP6] = 16 + 5;
t[SDLK_KP2] = 16 + 6;
@ -497,7 +496,7 @@ void initConfig() {
t['p'] = 32 + 10;
t['['] = 32 + pcCenter;
#ifndef MOBILE
#if ISMOBILE==0
t[SDLK_UP] = 48 ;
t[SDLK_RIGHT] = 48 + 1;
t[SDLK_DOWN] = 48 + 2;
@ -609,7 +608,7 @@ void loadConfig(FILE *f) {
#endif
void handleInput(int delta) {
#ifndef NOSDL
#if CAP_SDL
double d = delta / 500.;
Uint8 *keystate = SDL_GetKeyState(NULL);
@ -663,7 +662,7 @@ void handleInput(int delta) {
if(actionspressed[56] && !lactionpressed[56])
showMissionScreen();
#ifdef INV
#if CAP_INV
if(actionspressed[57] && !lactionpressed[57])
pushScreen(inv::show);
#endif
@ -1116,7 +1115,7 @@ bool isMonster(monster *m) { return m->type != moPlayer && m->type != moBullet;
void killMonster(monster* m, eMonster who_kills, int flags = 0) {
int tk = tkills();
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(m->type == moRogueviz) {
rogueviz::activate(m);
return;
@ -1185,59 +1184,46 @@ double playerturn[MAXPLAYER], playergo[MAXPLAYER];
bool playerfire[MAXPLAYER];
void awakenMimics(monster *m, cell *c2) {
for(int i=0; i<size(dcal); i++) {
cell *c = dcal[i];
if(isMimic(c->monst)) {
// straight
int i = 0;
// if(m->type == moMirror) i++;
if(c->monst == moMirror) i++;
transmatrix mirrortrans = Id;
if(i == 1) mirrortrans[0][0] = -1;
for(auto& mi: mirror::mirrors) {
cell *c = mi.second.c;
if(!gmatrix.count(c)) continue;
monster *m2 = new monster;
m2->type = c->monst;
c->monst = moNone;
m2->base = c;
if(isBullet(m)) {
m2->parenttype = m2->type;
m2->type = m->type;
m2->vel = m->vel;
m2->parent = m->parent;
m2->pid = m->pid;
}
if(m->type == moMirror) {
if(m2->type == moMirror) m2->type = moMirage;
else if(m2->type == moMirage) m2->type = moMirror;
}
hyperpoint H = inverse(gmatrix[c2]) * gmatrix[c] * C0;
transmatrix xfer = rgpushxto0(H);
transmatrix mirrortrans = Id;
if(mi.second.mirrored) mirrortrans[0][0] = -1;
if(i == 1) {
hyperpoint H2 = spintox(H) * H;
xfer = rspintox(H) * rpushxto0(H2) * mirrortrans * spintox(H);
}
m2->pat = gmatrix[c2] * xfer * inverse(gmatrix[c2]) * m->pat;
m2->at = inverse(gmatrix[c]) * m2->pat * mirrortrans;
m2->pid = cpid;
if(isBullet(m) && i == 1) m2->at = m2->at * spin(M_PI); // no idea why this
additional.push_back(m2);
// if you don't understand it, don't worry,
// I don't understand it either
if(!gmatrix.count(c)) continue;
monster *m2 = new monster;
m2->base = c;
if(isBullet(m)) {
m2->parenttype = m->parenttype;
m2->type = m->type;
m2->vel = m->vel;
m2->parent = m->parent;
m2->pid = m->pid;
}
else
m2->type = moMimic;
hyperpoint H = inverse(gmatrix[c2]) * gmatrix[c] * C0;
transmatrix xfer = rgpushxto0(H);
if(mi.second.mirrored) {
hyperpoint H2 = spintox(H) * H;
xfer = rspintox(H) * rpushxto0(H2) * mirrortrans * spintox(H);
}
m2->pat = gmatrix[c2] * xfer * inverse(gmatrix[c2]) * m->pat;
m2->at = inverse(gmatrix[c]) * m2->pat;
m2->pid = cpid;
additional.push_back(m2);
// if you don't understand it, don't worry,
// I don't understand it either
}
mirror::mirrors.clear();
}
int visibleAt;
@ -1452,6 +1438,11 @@ bool noncrashable(monster *m, monster *by) {
int bulltime[MAXPLAYER];
void reflect(cell*& c2, monster *m, transmatrix& nat);
// set to P_MIRRORWALL to allow the PCs to go through mirrors
static const int reflectflag = P_MIRRORWALL;
void movePlayer(monster *m, int delta) {
cpid = m->pid;
@ -1469,7 +1460,7 @@ void movePlayer(monster *m, int delta) {
int jb = 4*tableid[cpid];
for(int i=0; i<4; i++) if(axespressed[jb+i]) playermoved = true;
#ifndef MOBILE
#if !ISMOBILE
mgo = actionspressed[b+pcForward] - actionspressed[b+pcBackward] + axespressed[jb+2]/30000.;
mturn = actionspressed[b+pcTurnLeft] - actionspressed[b+pcTurnRight] + axespressed[jb+3]/30000.;
mdx = actionspressed[b+pcMoveRight] - actionspressed[b+pcMoveLeft] + axespressed[jb]/30000.;
@ -1478,9 +1469,8 @@ void movePlayer(monster *m, int delta) {
shotkey = actionspressed[b+pcFire] || actionspressed[b+pcFaceFire];
facemouse = actionspressed[b+pcFace] || actionspressed[b+pcFaceFire];
dropgreen = actionspressed[b+pcDrop];
#endif
#ifdef MOBILE
#else
mdx = mdy = mgo = mturn = 0;
facemouse = shotkey = false;
dropgreen = getcstat == 'g';
@ -1502,7 +1492,7 @@ void movePlayer(monster *m, int delta) {
targetRangedOrb(mouseover, roKeyboard);
}
#ifndef MOBILE
#if !ISMOBILE
if(haveRangedOrb()) {
cwt.c = m->base;
if(actionspressed[b+pcOrbKey] && !lactionpressed[b+pcOrbKey])
@ -1542,7 +1532,7 @@ void movePlayer(monster *m, int delta) {
mgo += mdd;
}
#ifndef NOSDL
#if CAP_SDL
Uint8 *keystate = SDL_GetKeyState(NULL);
bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]);
if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !mouseout()) {
@ -1600,6 +1590,7 @@ void movePlayer(monster *m, int delta) {
// spin(span[igo]) * xpush(playergo[cpid]) * spin(-span[igo]);
c2 = m->findbase(nat);
if(reflectflag & P_MIRRORWALL) reflect(c2, m, nat);
// don't have several players in one spot
// also don't let them run too far from each other!
@ -1623,7 +1614,7 @@ void movePlayer(monster *m, int delta) {
animateMovement(c2, m->base, LAYER_BOAT);
}
}
else if(m->inBoat && !isWateryOrBoat(c2) && passable(c2, m->base, P_ISPLAYER | P_MIRROR)) {
else if(m->inBoat && !isWateryOrBoat(c2) && passable(c2, m->base, P_ISPLAYER | P_MIRROR | reflectflag)) {
if(boatGoesThrough(c2) && markOrb(itOrbWater)) {
c2->wall = isIcyLand(m->base) ? waLake : waSea;
}
@ -1669,7 +1660,7 @@ void movePlayer(monster *m, int delta) {
go = false;
}
else if(
(blown ? !passable(c2, m->base, P_ISPLAYER | P_BLOW) : !passable(c2, m->base, P_ISPLAYER | P_MIRROR)) &&
(blown ? !passable(c2, m->base, P_ISPLAYER | P_BLOW) : !passable(c2, m->base, P_ISPLAYER | P_MIRROR | reflectflag)) &&
!(isWatery(c2) && m->inBoat && !nonAdjacent(m->base,c2)))
go = false;
@ -1703,20 +1694,12 @@ void movePlayer(monster *m, int delta) {
if(c2->item && c2->land == laAlchemist) c2->wall = m->base->wall;
if(m->base->wall == waRoundTable)
roundTableMessage(c2);
if(c2->wall == waCloud) {
if(c2->wall == waCloud || c2->wall == waMirror) {
visibleFor(500);
mirror::createMirages(c2, 0, moMirage);
cellwalker cw(c2, 0, false);
mirror::createHere(cw, cpid);
mirror::breakMirror(cw, cpid);
awakenMimics(m, c2);
c2->wall = waNone;
if(c2->land == laMirror) items[itShard]++;
}
if(c2->wall == waMirror) {
visibleFor(500);
cwt.c = c2;
mirror::createMirrors(c2, 0, moMirage);
awakenMimics(m, c2);
c2->wall = waNone;
if(c2->land == laMirror) items[itShard]++;
}
if(c2->wall == waGlass && items[itOrbAether]) {
items[itOrbAether] = 0;
@ -1869,6 +1852,59 @@ void virtualize(monster *m) {
}
}
bool reflectmatrix(transmatrix& M, cell *c1, cell *c2, bool onlypos) {
if(!gmatrix.count(c1) || !gmatrix.count(c2)) return false;
transmatrix H = inverse(gmatrix[c1]) * gmatrix[c2];
transmatrix S = spintox(tC0(H));
ld d = hdist0(tC0(H));
transmatrix T = xpush(-d/2) * S * inverse(gmatrix[c1]) * M;
if(onlypos && tC0(T)[0] < 0) return false;
M = gmatrix[c1] * inverse(S) * xpush(d/2) * MirrorX * T;
return true;
}
void reflect(cell*& c2, monster *m, transmatrix& nat) {
if(c2 != m->base && c2->wall == waMirrorWall && inmirror(c2)) {
if(reflectmatrix(nat, m->base, c2, false))
c2 = m->base;
}
if(c2 == m->base && inmirror(c2)) {
forCellEx(c3, c2) if(c3->land == laMirrorWall) {
cell *c1 = m->base;
m->base = c3;
reflect(c3, m, nat);
m->base = c1;
c2 = c3;
}
}
if(c2 == m->base && c2->wall == waMirrorWall && c2->land == laMirrorWall) {
int d = mirror::mirrordir(c2);
if(d != -1) {
for(int k=0; k<7; k++) {
cell *ca = createMovR(c2, d-k);
cell *cb = createMovR(c2, d+k);
if(ca->land == laMirror && inmirror(cb)) {
reflectmatrix(nat, ca, cb, true);
break;
}
}
}
else {
for(int k=0; k<6; k++) {
cell *cb = createMovR(c2, k+1);
cell *cc = createMovR(c2, k+2);
if(cb->land != laMirrorWall || cc->land != laMirrorWall) continue;
cell *ca = createMovR(c2, k);
cell *cd = createMovR(c2, k+3);
reflectmatrix(nat, cc, ca, true);
for(int limit=0; limit<10 && reflectmatrix(nat, cb, cd, true) && reflectmatrix(nat, cc, ca, true); limit++);
}
}
}
}
void moveMimic(monster *m) {
virtualize(m);
transmatrix nat = m->pat;
@ -1879,23 +1915,19 @@ void moveMimic(monster *m) {
nat = nat * spin(playerturn[cpid]) * xpush(playergo[cpid]);
cell *c2 = m->findbase(nat);
if(c2 != m->base && !passable(c2, m->base, P_ISPLAYER | P_MIRROR))
reflect(c2, m, nat);
if(c2 != m->base && !passable(c2, m->base, P_ISPLAYER | P_MIRROR | P_MIRRORWALL))
killMonster(m, moNone);
else {
m->rebasePat(nat);
if(playerfire[cpid]) shootBullet(m);
}
if(c2->wall == waCloud) {
mirror::createMirages(c2, 0, moMirage);
if(c2->wall == waCloud || c2->wall == waMirror) {
cellwalker cw(c2, 0, false);
mirror::createHere(cw, cpid);
mirror::breakMirror(cw, -1);
awakenMimics(m, c2);
c2->wall = waNone;
}
if(c2->wall == waMirror) {
mirror::createMirrors(c2, 0, moMirage);
awakenMimics(m, c2);
c2->wall = waNone;
}
if(!doall && c2->cpdist >= 6)
@ -1960,7 +1992,7 @@ eItem targetRangedOrbKey(orbAction a) {
for(monster *m2: nonvirtual) {
if(m2->dead) continue;
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(rogueviz::virt(m2)) continue;
#endif
if(!mousetarget || intval(mouseh, mousetarget->pat*C0) > intval(mouseh, m2->pat*C0))
@ -2058,22 +2090,18 @@ void moveBullet(monster *m, int delta) {
if(isActivable(c2)) activateActiv(c2, true);
// knives break mirrors and clouds
if(c2->wall == waCloud) {
mirror::createMirages(c2, 0, moMirage);
if(c2->wall == waCloud || c2->wall == waMirror) {
cellwalker cw(c2, 0, false);
mirror::createHere(cw, cpid);
mirror::breakMirror(cw, -1);
awakenMimics(m, c2);
c2->wall = waNone;
}
if(c2->wall == waMirror) {
cwt.c = c2;
mirror::createMirrors(c2, 0, moMirage);
awakenMimics(m, c2);
c2->wall = waNone;
}
reflect(c2, m, nat);
bool godragon = m->type == moFireball && isDragon(c2->monst);
if(m->type != moTongue && !(godragon || passable(c2, m->base, P_BULLET))) {
if(m->type != moTongue && !(godragon || passable(c2, m->base, P_BULLET | P_MIRRORWALL))) {
m->dead = true;
if(m->type != moAirball) killMonster(c2, m->parent ? m->parent->type : moNone);
// cell *c = m->base;
@ -2190,7 +2218,13 @@ void moveBullet(monster *m, int delta) {
// Orb of Winter protects from fireballs
if(m->type == moFireball && ((isPlayer(m2) && markOrb(itOrbWinter)) || m2->type == moWitchWinter))
continue;
bool revive = m2->type == moMirrorSpirit && !m2->dead;
killMonster(m2, m->parent ? m->parent->type : moNone);
if(revive && m2->dead) {
::kills[moMirrorSpirit]--;
multi::kills[cpid]--;
mirrorspirits++;
}
}
}
}
@ -2497,8 +2531,9 @@ void moveMonster(monster *m, int delta) {
if(crashintomon) { igo++; goto igo_retry; }
cell *c2 = m->findbase(nat);
if(reflectflag & P_MIRRORWALL) reflect(c2, m, nat);
if(m->type == moButterfly && !passable_for(m->type, c2, m->base, P_CHAIN)) {
if(m->type == moButterfly && !passable_for(m->type, c2, m->base, P_CHAIN | reflectflag)) {
igo++; goto igo_retry;
}
@ -2620,7 +2655,7 @@ void moveMonster(monster *m, int delta) {
m->base->wall = waBigStatue;
animateMovement(c2, m->base, LAYER_BOAT);
}
if(passable_for(m->type, c2, m->base, P_CHAIN | P_ONPLAYER) && !isWatery(c2) && m->inBoat) {
if(passable_for(m->type, c2, m->base, P_CHAIN | P_ONPLAYER | reflectflag) && !isWatery(c2) && m->inBoat) {
if(isWatery(m->base))
m->base->wall = waBoat, m->base->mondir = dirfromto(m->base, c2);
else if(boatStrandable(c2)) c2->wall = waStrandedBoat;
@ -2637,7 +2672,7 @@ void moveMonster(monster *m, int delta) {
}
if(!(m->type == moRoseBeauty && c2->land != laRose)) {
if(stunned ? passable(c2, m->base, P_BLOW) : passable_for(m->type, c2, m->base, P_CHAIN)) {
if(stunned ? passable(c2, m->base, P_BLOW | reflectflag) : passable_for(m->type, c2, m->base, P_CHAIN | reflectflag)) {
if(c2 != m->base && m->type == moButterfly)
m->torigin = m->base;
m->rebasePat(nat);
@ -2889,6 +2924,8 @@ void turn(int delta) {
if(elec::havecharge) elec::act();
popmonsters();
bool lastcanmove = canmove;
canmove = true;
for(int i=0; i<players; i++) {
@ -2934,6 +2971,8 @@ void turn(int delta) {
achievement_final(true);
}
lastdead = pc[i]->dead;
if(lastcanmove && pc[i]->dead) showMissionScreen();
canmove = canmove && !pc[i]->dead;
}
@ -2961,7 +3000,7 @@ void turn(int delta) {
safety = false;
}
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
rogueviz::turn(delta);
#endif
}
@ -3030,7 +3069,7 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
transmatrix view = V * m->at;
if(!mouseout()) {
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(rogueviz::virt(m)) ; else
#endif
if(mapeditor::drawplayer || m->type != moPlayer)
@ -3077,6 +3116,8 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
cpid = m->pid;
if(m->parenttype == moPlayer)
col = getcs().swordcolor;
else if(m->parenttype == moMimic)
col = (mirrorcolor(det(view) < 0) << 8) | 0xFF;
else
col = (minf[m->parenttype].color << 8) | 0xFF;
if(getcs().charid >= 4) {
@ -3107,7 +3148,7 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
break;
}
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
case moRogueviz:
rogueviz::drawVertex(V, c, m);
break;
@ -3116,6 +3157,8 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
default:
if(m->inBoat) m->footphase = 0;
int col = minf[m->type].color;
if(m->type == moMimic)
col = mirrorcolor(det(view) < 0);
if(m->type == moSlime) {
col = winf[c->wall].color;
col |= (col >> 1);
@ -3352,7 +3395,7 @@ void virtualRebase(shmup::monster *m, bool tohex) {
void addShmupHelp(string& out) {
if(shmup::mousetarget && intval(mouseh, tC0(shmup::mousetarget->pat)) < .1) {
out += ", ";
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
if(shmup::mousetarget->type == moRogueviz) {
help = XLAT(minf[shmup::mousetarget->type].help);
out += rogueviz::describe(shmup::mousetarget);

View File

@ -55,7 +55,7 @@ void playSeenSound(cell *c) {
playSound(c, "seen-cultistleader");
}
#ifdef SDLAUDIO
#if CAP_SDLAUDIO
bool loaded[landtypes];
Mix_Music* music[landtypes];

View File

@ -15,10 +15,11 @@ bool timerstopped;
int savecount;
bool showoff = false, doCross = false;
bool verless(const string& v, const string& cmp) {
// no checks exists for versions greater than 10.0 yet
if(isdigit(v[0]) && isdigit(v[1]))
return false;
bool verless(string v, string cmp) {
if(isdigit(v[0]) && isdigit(v[1]))
v = "A" + v;
if(isdigit(cmp[0]) && isdigit(cmp[1]))
cmp = "A" + cmp;
return v < cmp;
}
@ -161,7 +162,7 @@ void initgame() {
peace::simon::init();
multi::revive_queue.clear();
#ifdef TOUR
#if CAP_TOUR
if(tour::on) tour::presentation(tour::pmRestart);
#endif
@ -191,14 +192,14 @@ void initgame() {
timerghost = true;
truelotus = 0;
survivalist = true;
#ifdef INV
#if CAP_INV
if(inv::on) inv::init();
#endif
if(!randomPatternsMode && !tactic::on && !yendor::on && !peace::on) {
if(firstland != (princess::challenge ? laPalace : laIce)) cheater++;
}
if(tactic::trailer) ;
#ifdef TOUR
#if CAP_TOUR
else if(tour::on) ; // displayed by tour
#endif
else if(princess::challenge) {
@ -232,20 +233,21 @@ void initgame() {
addMessage(XLAT("Good luck in the elliptic plane!"));
else if(sphere)
addMessage(XLAT("Welcome to Spherogue!"));
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
else if(rogueviz::on)
addMessage(XLAT("Welcome to RogueViz!"));
#endif
else {
addMessage(XLAT("Welcome to HyperRogue!"));
#ifndef MOBILE
#ifdef IOS
#if ISMAC
addMessage(XLAT("Press F1 or right-shift-click things for help."));
#else
#elif !ISMOBILE
addMessage(XLAT("Press F1 or right-click things for help."));
#endif
#endif
}
if(shmup::on && (euclidland == laMirror || euclidland == laMirrorOld) && (geometry == gElliptic || geometry == gQuotient))
addMessage(XLAT("This combination is known to be buggy at the moment."));
}
else {
usedSafety = true;
@ -262,7 +264,7 @@ void initgame() {
bool havesave = true;
#ifndef NOSAVE
#if CAP_SAVE
#define MAXBOX 500
#define POSSCORE 308 // update this when new boxes are added!
@ -335,7 +337,7 @@ void applyBoxOrb(eItem it) {
void list_invorb() {
for(eItem it: invorb) {
#ifdef INV
#if CAP_INV
if(true) {
inv::applyBox(it);
continue;
@ -612,7 +614,7 @@ void applyBoxes() {
addinv(itGreenStone);
list_invorb();
applyBoxBool(inv::on, "inventory"); // 306
#ifdef INV
#if CAP_INV
applyBoxNum(inv::rseed);
#else
{ int u; applyBoxNum(u); }
@ -652,7 +654,7 @@ void loadBoxHigh() {
// certify that saves and achievements were received
// in an official version of HyperRogue
#ifdef CERTIFY
#if CAP_CERTIFY
#include "private/certify.cpp"
#else
@ -673,7 +675,7 @@ long long saveposition = -1;
#include <sys/types.h>
void remove_emergency_save() {
#ifndef WINDOWS
#if !ISWINDOWS
if(saveposition >= 0) {
/* if(!timerghost)
addMessage(XLAT("Emergency truncate to ") + its(saveposition)); */
@ -687,7 +689,7 @@ void saveStats(bool emergency = false) {
DEBB(DF_INIT, (debugfile,"saveStats [%s]\n", scorefile));
if(autocheat) return;
#ifdef TOUR
#if CAP_TOUR
if(tour::on) return;
#endif
if(randomPatternsMode) return;
@ -804,7 +806,7 @@ void saveStats(bool emergency = false) {
fprintf(f, "\n\n\n");
#ifndef MOBILE
#if ISMOBILE==0
DEBB(DF_INIT, (debugfile, "Game statistics saved to %s\n", scorefile));
if(!tactic::trailer)
addMessage(XLAT("Game statistics saved to %1", scorefile));
@ -815,7 +817,7 @@ void saveStats(bool emergency = false) {
// load the save
void loadsave() {
if(autocheat) return;
#ifdef TOUR
#if CAP_TOUR
if(tour::on) return;
#endif
DEBB(DF_INIT, (debugfile,"loadSave\n"));
@ -876,14 +878,15 @@ void loadsave() {
int tid, land, score, tc, t, ts, cert;
sscanf(buf, "%70s%10s%d%d%d%d%d%d%d",
buf1, ver, &tid, &land, &score, &tc, &t, &ts, &cert);
eLand l2 = eLand(land);
if(land == laMirror && verless(ver, "10.0")) l2 = laMirrorOld;
for(int xc=0; xc<MODECODES; xc++)
if(tid == tactic::id && (anticheat::check(cert, ver, dnameof(eLand(land)), tc, t, ts, xc*999+tid + 256 * score))) {
if(tid == tactic::id && (anticheat::check(cert, ver, dnameof(l2), tc, t, ts, xc*999+tid + 256 * score))) {
if(score != 0
&& !(land == laOcean && verless(ver, "8.0f"))
&& !(land == laMirror && verless(ver, "10.0"))
)
tactic::record(eLand(land), score, xc);
) tactic::record(l2, score, xc);
anticheat::nextid(tactic::id, ver, cert);
break;
}
@ -993,7 +996,7 @@ void restartGame(char switchWhat, bool push) {
}
else {
achievement_final(true);
#ifndef NOSAVE
#if CAP_SAVE
saveStats();
#endif
for(int i=0; i<ittypes; i++) items[i] = 0;
@ -1006,7 +1009,7 @@ void restartGame(char switchWhat, bool push) {
if(multi::playerActive(i))
multi::deaths[i]++;
#ifndef NOSAVE
#if CAP_SAVE
anticheat::tampered = false;
#endif
achievementsReceived.clear();
@ -1036,7 +1039,7 @@ void restartGame(char switchWhat, bool push) {
resetGeometry();
chaosmode = !chaosmode;
}
#ifdef TOUR
#if CAP_TOUR
if(switchWhat == 'T') {
geometry = gNormal;
yendor::on = tactic::on = princess::challenge = peace::on = inv::on = false;
@ -1173,13 +1176,6 @@ void cheatMoveTo(eLand l) {
bool applyCheat(char u, cell *c = NULL) {
if(u == 'M' && cwt.c->type == 6) {
addMessage(XLAT("You summon some Mirages!"));
cheater++;
mirror::createMirrors(cwt.c, cwt.spin, moMirage),
mirror::createMirages(cwt.c, cwt.spin, moMirage);
return true;
}
if(u == 'G') {
addMessage(XLAT("You summon a golem!"));
cheater++;
@ -1256,7 +1252,7 @@ bool applyCheat(char u, cell *c = NULL) {
return true;
}
if(u == 'R'-64) buildRosemap();
#ifndef NOEDIT
#if CAP_EDIT
if(u == 'A') {
lastexplore = turncount;
pushScreen(mapeditor::showMapEditor);
@ -1357,7 +1353,7 @@ bool applyCheat(char u, cell *c = NULL) {
}
if(u == 'Z') {
flipplayer = false;
mirror::spin(1);
mirror::act(1, mirror::SPINSINGLE);
cwspin(cwt, 1);
return true;
}

View File

@ -11,10 +11,6 @@ string tourhelp;
int currentslide;
// #ifdef PRES
// #include "presentation.cpp"
// #else
// modes:
// 1 - enter the slide
// 2 - each frame
@ -53,10 +49,6 @@ string slidecommand;
void presentation(presmode mode) {
#ifdef PRES
presentation2(mode);
#endif
cheater = 0;
if(mode == pmStart) tourhelp = XLAT(slides[currentslide].name);
@ -323,7 +315,7 @@ slide default_slides[] = {
else clearMessages();
}
SHOWLAND( l == laIce );
#ifdef ROGUEVIZ
#if CAP_ROGUEVIZ
slidecommand = "RogueViz presentation";
if(mode == 1)
help +=
@ -362,7 +354,7 @@ slide default_slides[] = {
},
{"Hypersian Rug model", 21, LEGAL_HYPERBOLIC,
"New players think that the action of HyperRogue takes place on a sphere. "
#ifdef WEB
#if CAP_RUG
"This is not true -- the Tutorial in the native desktop version shows "
"the surface HyperRogue actually takes place on.",
#else
@ -372,8 +364,8 @@ slide default_slides[] = {
"If you do not see anything, press '5' to try a safer renderer.",
#endif
[] (presmode mode) {
#if CAP_RUG
static int wm, mm;
#ifndef NORUG
if(mode == 1) {
rug::init();
wm = vid.wallmode;
@ -467,7 +459,7 @@ slide default_slides[] = {
"it will appear to go slower -- this is because you are running "
"in a straight line, and the Running Dog has to run in a curve "
"called an equidistant.\n\n"
#ifdef MAC
#if ISMAC
"Remember that you can click with right Shift on anything to get more information.",
#else
"Remember that you can right click on anything to get more information.",
@ -705,7 +697,7 @@ slide default_slides[] = {
centerpc(INF);
conformal::includeHistory = false;
}
#ifndef NOSDL
#if CAP_SDL
slidecommand = "render spiral";
if(mode == 4) conformal::createImage(true);
if(mode == 11) conformal::create();
@ -720,7 +712,7 @@ slide default_slides[] = {
if(mode == 3) pmodel = mdDisk;
}
},
#ifndef WEB
#if !ISWEB
{"Shoot'em up mode", 52, LEGAL_NONE,
"In the shoot'em up mode, space and time is continuous. "
"You attack by throwing knives. "

View File

@ -3,15 +3,7 @@
// basic utility functions
#ifdef MOBWEB
#define MWP
#endif
#ifdef PANDORA
#define MWP
#endif
#ifdef MWP
#if ISMOBILE || ISWEB || ISPANDORA
typedef double ld;
#define LDF "%lf"
#define PLDF "lf"
@ -50,7 +42,7 @@ string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
extern FILE *debugfile;
extern int debugflags;
#ifdef ANDROID
#if ISANDROID
#define DEBB(r,x)
#else
#define DEBB(r,x) { if(debugfile && (!(r) || (debugflags & (r)))) { fprintf x; fflush(debugfile); } }
@ -63,7 +55,7 @@ extern int debugflags;
#define DF_TURN 4
#define DF_FIELD 8
#ifdef PROFILING
#if CAP_PROFILING
#include <sys/time.h>
long long getms() {

View File

@ -90,7 +90,7 @@ namespace yendor {
{laMotion, YF_START_AL | YF_END}, // NOT WON, SEEMS OKAY
{laAlchemist, 0}, // ALMOST WON
{laIvoryTower,YF_START_CR | YF_NEAR_ELEM | YF_REPEAT}, // won cool
{laMirror, YF_NEAR_OVER}, // OK
{laMirrorOld, YF_NEAR_OVER}, // OK
{laWhirlpool, 0}, // cool
{laIce, YF_NEAR_ELEM}, // OK
{laHive, YF_NEAR_RED}, // OK
@ -668,6 +668,7 @@ namespace tactic {
}
void showMenu() {
cmode = sm::ZOOMABLE;
mouseovers = XLAT("pure tactics mode") + " - " + mouseovers;
nl = LAND_TAC;
@ -830,9 +831,9 @@ int modecodetable[42][6] = {
int newmodecode = 255;
int modecode() {
#ifndef NOSAVE
#if CAP_SAVE
if(anticheat::tampered || cheater) return 6;
#ifdef TOUR
#if CAP_TOUR
if(tour::on) return 6;
#endif
if(quotient) return 6;
@ -950,8 +951,19 @@ namespace peace {
return false;
}
const char *chelp = NODESCYET;
const char *chelp =
"In the peaceful mode, you just explore the world, "
"without any battles; there are also several "
"navigational puzzles available. In the memory game, "
"you have to collect as many Dodecahedra as you can, "
"and return to the starting point -- hyperbolic geometry "
"makes this extremely difficult! Other hyperbolic puzzles "
"include the Burial Grounds (excavate the treasures "
"using your magical sword), Galápagos (try to find an adult "
"tortoise matching the baby), Camelot (find the center of "
"a large hyperbolic circle), and Palace (follow the mouse). "
"Other places listed are for exploration.";
namespace simon {
vector<cell*> path;
@ -1028,7 +1040,7 @@ namespace peace {
}
void showMenu() {
dialog::init(XLAT(otherpuzzles ? "hyperbolic puzzles" : "memory game"), 0x40A040, 150, 100);
dialog::init(XLAT(otherpuzzles ? "puzzles and exploration" : "memory game"), 0x40A040, 150, 100);
levellist = otherpuzzles ? explorelevels : simonlevels;
@ -1036,9 +1048,9 @@ namespace peace {
dialog::addItem(XLAT1(linf[levellist[qty]].name), 'a'+qty);
dialog::addBreak(100);
dialog::addItem(XLAT(otherpuzzles ? "memory game" : "other hyperbolic puzzles"), '1');
dialog::addItem(XLAT(otherpuzzles ? "memory game" : "puzzles and exploration"), '1');
dialog::addBoolItem(XLAT("display hints"), hint, '2');
dialog::addItem(XLAT("Help"), SDLK_F1);
dialog::addItem(XLAT("help"), SDLK_F1);
dialog::addItem(XLAT("Return to the normal game"), '0');
dialog::display();