1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-25 01:20:37 +00:00

Updated to 9.4g (mostly tutorial fixes)

This commit is contained in:
Zeno Rogue 2017-04-14 20:12:23 +02:00
parent 27c1b678c2
commit c52625e7ca
17 changed files with 686 additions and 450 deletions

View File

@ -107,7 +107,6 @@ struct celllister {
if(c == last) { if(c == last) {
if(size(lst) >= maxcount || dists[i]+1 == maxdist) break; if(size(lst) >= maxcount || dists[i]+1 == maxdist) break;
last = lst[size(lst)-1]; last = lst[size(lst)-1];
maxdist--;
} }
} }
} }
@ -137,7 +136,9 @@ struct hrmap_alternate : hrmap {
struct hrmap_hyperbolic : hrmap { struct hrmap_hyperbolic : hrmap {
heptagon *origin; heptagon *origin;
bool ispurehepta;
hrmap_hyperbolic() { hrmap_hyperbolic() {
// printf("Creating hyperbolic map: %p\n", this);
origin = new heptagon; origin = new heptagon;
heptagon& h = *origin; heptagon& h = *origin;
h.s = hsOrigin; h.s = hsOrigin;
@ -151,11 +152,14 @@ struct hrmap_hyperbolic : hrmap {
h.spintable = 0; h.spintable = 0;
h.alt = NULL; h.alt = NULL;
h.distance = 0; h.distance = 0;
ispurehepta = purehepta;
h.c7 = newCell(7, origin); h.c7 = newCell(7, origin);
} }
heptagon *getOrigin() { return origin; } heptagon *getOrigin() { return origin; }
~hrmap_hyperbolic() { ~hrmap_hyperbolic() {
DEBMEM ( verifycells(origin); ) DEBMEM ( verifycells(origin); )
// printf("Deleting hyperbolic map: %p\n", this);
dynamicval<bool> ph(purehepta, ispurehepta);
clearfrom(origin); clearfrom(origin);
} }
void verify() { verifycells(origin); } void verify() { verifycells(origin); }
@ -174,8 +178,10 @@ int spherecells() {
struct hrmap_spherical : hrmap { struct hrmap_spherical : hrmap {
heptagon *dodecahedron[12]; heptagon *dodecahedron[12];
bool ispurehepta;
hrmap_spherical() { hrmap_spherical() {
ispurehepta = purehepta;
for(int i=0; i<spherecells(); i++) { for(int i=0; i<spherecells(); i++) {
heptagon& h = *(dodecahedron[i] = new heptagon); heptagon& h = *(dodecahedron[i] = new heptagon);
h.s = hsOrigin; h.s = hsOrigin;
@ -240,6 +246,7 @@ struct hrmap_spherical : hrmap {
heptagon *getOrigin() { return dodecahedron[0]; } heptagon *getOrigin() { return dodecahedron[0]; }
~hrmap_spherical() { ~hrmap_spherical() {
dynamicval<bool> ph(purehepta, ispurehepta);
for(int i=0; i<spherecells(); i++) clearHexes(dodecahedron[i]); for(int i=0; i<spherecells(); i++) clearHexes(dodecahedron[i]);
for(int i=0; i<spherecells(); i++) delete dodecahedron[i]; for(int i=0; i<spherecells(); i++) delete dodecahedron[i];
} }

View File

@ -1609,7 +1609,7 @@ namespace heat {
for(int i=0; i<dcs; i++) { for(int i=0; i<dcs; i++) {
bool readd = false; bool readd = false;
cell *c = allcells[i]; cell *c = allcells[i];
double xrate = (c->land == laCocytus && shmup::on) ? rate/3 : rate; double xrate = (c->land == laCocytus && shmup::on) ? 1/3. : 1;
if(purehepta) xrate *= 1.7; if(purehepta) xrate *= 1.7;
if(!shmup::on) xrate /= FIX94; if(!shmup::on) xrate /= FIX94;
if(c->cpdist > 7 && !quotient) break; if(c->cpdist > 7 && !quotient) break;
@ -1689,7 +1689,7 @@ namespace heat {
// make sure that we can still enter Cocytus, // make sure that we can still enter Cocytus,
// it won't heat up right away even without Orb of Winter or Orb of Speed // it won't heat up right away even without Orb of Winter or Orb of Speed
if(isPlayerOn(c->mov[j]) && (c->land == laIce || markOrb(itOrbWinter))) if(isPlayerOn(c->mov[j]) && (c->land == laIce || markOrb(itOrbWinter)))
hmod += (markOrb(itOrbWinter) ? -1.2 : 1.2) / 4; hmod += (markOrb(itOrbWinter) ? -1.2 : 1.2) / 4 * xrate;
continue; continue;
} }
ld hdiff = absheat(c->mov[j]) - absheat(c); ld hdiff = absheat(c->mov[j]) - absheat(c);
@ -1700,7 +1700,7 @@ namespace heat {
hmod += hdiff; hmod += hdiff;
} }
hmods[i] = hmod * rate; hmods[i] = hmod;
} }
if((readd || HEAT(c)) && !quotient) if((readd || HEAT(c)) && !quotient)
@ -2061,8 +2061,10 @@ namespace dragon {
if(c->mov[i] && isDragon(c->mov[i]->monst) && c->mov[i]->mondir == c->spn(i)) { if(c->mov[i] && isDragon(c->mov[i]->monst) && c->mov[i]->mondir == c->spn(i)) {
c = c->mov[i]; goto findhead; c = c->mov[i]; goto findhead;
} }
if(!conformal::includeHistory) {
printf("dragon bug #3 (%p -> %p)\n", cor, c); printf("dragon bug #3 (%p -> %p)\n", cor, c);
dragbugs = true; dragbugs = true;
}
c->monst = moDragonHead; return c; c->monst = moDragonHead; return c;
} }
@ -2130,7 +2132,7 @@ namespace dragon {
int maxlen = 1000; int maxlen = 1000;
while(maxlen-->0) { while(maxlen-->0) {
if(!isDragon(c->monst)) { if(!isDragon(c->monst)) {
printf("dragon bug #4\n"); if(!conformal::includeHistory) printf("dragon bug #4\n");
return total; return total;
} }
total += c->hitpoints; total += c->hitpoints;
@ -2169,7 +2171,10 @@ namespace dragon {
} }
if(c->mondir == NODIR) { printf("dragon bug\n"); break; } if(c->mondir == NODIR) { printf("dragon bug\n"); break; }
c = c->mov[c->mondir]; c = c->mov[c->mondir];
if(!c) { printf("dragon bug #2\n"); break; } if(!c) {
if(!conformal::includeHistory) printf("dragon bug #2\n");
break;
}
} }
} }

View File

@ -20,6 +20,7 @@ namespace polygonal {
int maxcoef, coefid; int maxcoef, coefid;
void solve() { void solve() {
if(SI < 3) SI = 3;
for(int i=0; i<MSI; i++) ans[i] = cos(M_PI / SI); for(int i=0; i<MSI; i++) ans[i] = cos(M_PI / SI);
for(int i=0; i<MSI; i++) for(int i=0; i<MSI; i++)
for(int j=0; j<MSI; j++) { for(int j=0; j<MSI; j++) {

View File

@ -5392,6 +5392,9 @@ void movecost(cell* from, cell *to) {
addMessage(XLAT("As you leave, your powers are drained!")); addMessage(XLAT("As you leave, your powers are drained!"));
} }
if(from->land != to->land && tour::on)
tour::checkGoodLand(to->land);
if(to->land ==laCrossroads4 && !chaosUnlocked) { if(to->land ==laCrossroads4 && !chaosUnlocked) {
achievement_gain("CR4"); achievement_gain("CR4");
chaosUnlocked = true; chaosUnlocked = true;
@ -5571,6 +5574,10 @@ bool collectItem(cell *c2, bool telekinesis) {
if(shmup::on) gainLife(); if(shmup::on) gainLife();
else placeGolem(cwt.c, c2, moTameBomberbird); else placeGolem(cwt.c, c2, moTameBomberbird);
} }
else if(tour::on && (c2->item == itOrbSafety || c2->item == itOrbRecall)) {
addMessage(XLAT("This Orb is not compatible with the Tutorial."));
return true;
}
else if(c2->item == itOrbSafety) { else if(c2->item == itOrbSafety) {
playSound(c2, "pickup-orb"); // TODO safety playSound(c2, "pickup-orb"); // TODO safety
items[c2->item] += 7; items[c2->item] += 7;
@ -6988,6 +6995,7 @@ void moveItem (cell *from, cell *to, bool activateYendor) {
} }
void fixWormBug(cell *c) { void fixWormBug(cell *c) {
if(conformal::includeHistory) return;
printf("worm bug!\n"); printf("worm bug!\n");
if(c->monst == moWormtail) c->monst = moWormwait; if(c->monst == moWormtail) c->monst = moWormwait;
if(c->monst == moTentacletail || c->monst == moTentacleGhost) c->monst = moTentacle; if(c->monst == moTentacletail || c->monst == moTentacleGhost) c->monst = moTentacle;

View File

@ -930,14 +930,14 @@ void ghcheck(hyperpoint &ret, const hyperpoint &H) {
hyperpoint gethyper(ld x, ld y) { hyperpoint gethyper(ld x, ld y) {
if(pmodel) {
ghx = x, ghy = y;
return ghpm;
}
ld hx = (x - vid.xcenter) / vid.radius; ld hx = (x - vid.xcenter) / vid.radius;
ld hy = (y - vid.ycenter) / vid.radius; ld hy = (y - vid.ycenter) / vid.radius;
if(pmodel) {
ghx = hx, ghy = hy;
return ghpm;
}
if(euclid) if(euclid)
return hpxy(hx * (EUCSCALE + vid.alphax), hy * (EUCSCALE + vid.alphax)); return hpxy(hx * (EUCSCALE + vid.alphax), hy * (EUCSCALE + vid.alphax));
@ -1014,6 +1014,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
double d = hdist0(H); double d = hdist0(H);
ballmodel(ret, alpha, d, zl); ballmodel(ret, alpha, d, zl);
ghcheck(ret,H);
return; return;
} }
@ -1026,6 +1027,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
ret[0] = H[0] / 3; ret[0] = H[0] / 3;
ret[1] = (1 - H[2]) / 3 * cb + H[1] / 3 * sb; ret[1] = (1 - H[2]) / 3 * cb + H[1] / 3 * sb;
ret[2] = H[1] / 3 * cb - (1 - H[2]) / 3 * sb; ret[2] = H[1] / 3 * cb - (1 - H[2]) / 3 * sb;
ghcheck(ret,H);
return; return;
} }
@ -1115,7 +1118,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
} */ } */
ret[0] = x0/M_PI*2; ret[0] = x0/M_PI*2;
ret[1] = y0/M_PI*2; ret[1] = -y0/M_PI*2;
ret[2] = 0; ret[2] = 0;
if(zlev != 1 && vid.goteyes) if(zlev != 1 && vid.goteyes)
@ -4323,6 +4326,9 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
else if(c->land == laRose) else if(c->land == laRose)
qfloor(c, Vf, shOverFloor[ECT], darkena(fcol, fd, 0xFF)); qfloor(c, Vf, shOverFloor[ECT], darkena(fcol, fd, 0xFF));
else if(c->land == laBull)
qfloor(c, Vf, (eoh ? shFloor : shButterflyFloor)[ct6], darkena(fcol, fd, 0xFF));
else if(c->land == laDryForest) else if(c->land == laDryForest)
qfloor(c, Vf, (eoh ? shStarFloor : shDesertFloor)[ct6], darkena(fcol, fd, 0xFF)); qfloor(c, Vf, (eoh ? shStarFloor : shDesertFloor)[ct6], darkena(fcol, fd, 0xFF));
@ -6813,7 +6819,12 @@ void showGameover() {
dialog::addItem("Euclidean geometry", '2'); dialog::addItem("Euclidean geometry", '2');
dialog::addItem("more curved hyperbolic geometry", '3'); dialog::addItem("more curved hyperbolic geometry", '3');
} }
if(!items[itOrbTeleport])
dialog::addItem("teleport away", '4'); dialog::addItem("teleport away", '4');
else if(!items[itOrbAether])
dialog::addItem("move through walls", '4');
else
dialog::addItem("flash", '4');
if(canmove) { if(canmove) {
dialog::addItem("slide-specific command", '5'); dialog::addItem("slide-specific command", '5');
dialog::addItem("static mode", '6'); dialog::addItem("static mode", '6');
@ -6821,6 +6832,8 @@ void showGameover() {
dialog::addItem("next slide", SDLK_RETURN); dialog::addItem("next slide", SDLK_RETURN);
dialog::addItem("previous slide", SDLK_BACKSPACE); dialog::addItem("previous slide", SDLK_BACKSPACE);
} }
else
dialog::addBreak(200);
dialog::addItem("main menu", 'v'); dialog::addItem("main menu", 'v');
} }
else { else {
@ -8383,20 +8396,43 @@ void handlekey(int sym, int uni, extra& ev) {
if(((cmode == emNormal && canmove) || (cmode == emQuit && !canmove) || cmode == emDraw || cmode == emMapEditor) && DEFAULTCONTROL && !rug::rugged) { if(((cmode == emNormal && canmove) || (cmode == emQuit && !canmove) || cmode == emDraw || cmode == emMapEditor) && DEFAULTCONTROL && !rug::rugged) {
#ifndef PANDORA #ifndef PANDORA
if(sym == SDLK_RIGHT) if(sym == SDLK_RIGHT) {
if(conformal::on)
conformal::lvspeed += 0.1 * shiftmul;
else
View = xpush(-0.2*shiftmul) * View, playermoved = false, didsomething = true; View = xpush(-0.2*shiftmul) * View, playermoved = false, didsomething = true;
if(sym == SDLK_LEFT) }
if(sym == SDLK_LEFT) {
if(conformal::on)
conformal::lvspeed -= 0.1 * shiftmul;
else
View = xpush(+0.2*shiftmul) * View, playermoved = false, didsomething = true; View = xpush(+0.2*shiftmul) * View, playermoved = false, didsomething = true;
if(sym == SDLK_UP) }
if(sym == SDLK_UP) {
if(conformal::on)
conformal::lvspeed += 0.1 * shiftmul;
else
View = ypush(+0.2*shiftmul) * View, playermoved = false, didsomething = true; View = ypush(+0.2*shiftmul) * View, playermoved = false, didsomething = true;
if(sym == SDLK_DOWN) }
if(sym == SDLK_DOWN) {
if(conformal::on)
conformal::lvspeed -= 0.1 * shiftmul;
else
View = ypush(-0.2*shiftmul) * View, playermoved = false, didsomething = true; View = ypush(-0.2*shiftmul) * View, playermoved = false, didsomething = true;
}
#endif #endif
if(sym == SDLK_PAGEUP) { if(sym == SDLK_PAGEUP) {
if(conformal::on)
conformal::rotation++;
else
View = spin(M_PI/S21*shiftmul) * View, didsomething = true; View = spin(M_PI/S21*shiftmul) * View, didsomething = true;
} }
if(sym == SDLK_PAGEDOWN) if(sym == SDLK_PAGEDOWN) {
if(conformal::on)
conformal::rotation++;
else
View = spin(-M_PI/S21*shiftmul) * View, didsomething = true; View = spin(-M_PI/S21*shiftmul) * View, didsomething = true;
}
if(sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN) if(sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN)
if(isGravityLand(cwt.c->land)) playermoved = false; if(isGravityLand(cwt.c->land)) playermoved = false;

View File

@ -219,6 +219,7 @@ namespace shmup {
extern bool on; extern bool on;
extern bool safety; extern bool safety;
extern int curtime; extern int curtime;
void clearMonsters();
void clearMemory(); void clearMemory();
void init(); void init();
void teleported(); void teleported();
@ -1141,6 +1142,7 @@ namespace tour {
bool handleKeyTour(int sym, int uni); bool handleKeyTour(int sym, int uni);
void presentation(int mode); void presentation(int mode);
void checkGoodLand(eLand l);
int getid(); int getid();
eLand getNext(eLand old); eLand getNext(eLand old);

View File

@ -1,8 +1,8 @@
id ICON "hr-icon.ico" id ICON "hr-icon.ico"
1 VERSIONINFO 1 VERSIONINFO
FILEVERSION 8,3,0,10 FILEVERSION 9,4,0,7
PRODUCTVERSION 8,3,0,10 PRODUCTVERSION 9,4,0,7
BEGIN BEGIN
BLOCK "StringFileInfo" BLOCK "StringFileInfo"
BEGIN BEGIN
@ -15,7 +15,7 @@ BEGIN
VALUE "LegalCopyright", "Zeno Rogue" VALUE "LegalCopyright", "Zeno Rogue"
VALUE "OriginalFilename", "hyper.exe" VALUE "OriginalFilename", "hyper.exe"
VALUE "ProductName", "HyperRogue" VALUE "ProductName", "HyperRogue"
VALUE "ProductVersion", "8.3j" VALUE "ProductVersion", "9.4g"
END END
END END

View File

@ -1,6 +1,6 @@
#define VER "9.4f" #define VER "9.4g"
#define VERNUM 9406 #define VERNUM 9407
#define VERNUM_HEX 0x9406 #define VERNUM_HEX 0x9407
#define GEN_M 0 #define GEN_M 0
#define GEN_F 1 #define GEN_F 1

View File

@ -2869,6 +2869,7 @@ void buildBigStuff(cell *c, cell *from) {
(c->land != laRlyeh || rlyehComplete()) && (c->land != laRlyeh || rlyehComplete()) &&
c->land != laTortoise && c->land != laPrairie && c->land && c->land != laTortoise && c->land != laPrairie && c->land &&
!(c->land == laGraveyard && !deepOcean) !(c->land == laGraveyard && !deepOcean)
&& c->land != laCanvas
) { ) {
buildBarrierNowall(c, laCrossroads4) ; buildBarrierNowall(c, laCrossroads4) ;
} }

View File

@ -1493,6 +1493,7 @@ void showDemo() {
dialog::addBreak(50); dialog::addBreak(50);
dialog::addItem(XLAT("play"), 'f'); dialog::addItem(XLAT("play"), 'f');
dialog::addItem(XLAT("tutorial"), 't');
dialog::addItem(XLAT("help"), 'h'); dialog::lastItem().keycaption += " / F1"; dialog::addItem(XLAT("help"), 'h'); dialog::lastItem().keycaption += " / F1";
dialog::addItem(XLAT("toggle high detail"), 'a'); dialog::addItem(XLAT("toggle high detail"), 'a');
dialog::addBreak(100); dialog::addBreak(100);
@ -1521,6 +1522,11 @@ void handleDemoKey(int sym, int uni) {
else restartGame(); else restartGame();
cmode = emNormal; cmode = emNormal;
} }
else if(sym == 't') {
firstland = laIce;
if(!tour::on) restartGame('T');
cmode = emNormal;
}
else if(sym == 't') { else if(sym == 't') {
firstland = laTemple; firstland = laTemple;
if(!tactic::on) restartGame('t'); if(!tactic::on) restartGame('t');

File diff suppressed because it is too large Load Diff

View File

@ -178,8 +178,11 @@ void addedge(int i, int j, edgeinfo *ei) {
else addedge0(i, j, ei); else addedge0(i, j, ei);
} }
vector<edgeinfo*> edgeinfos;
void addedge(int i, int j, double wei, bool subdiv) { void addedge(int i, int j, double wei, bool subdiv) {
edgeinfo *ei = new edgeinfo; edgeinfo *ei = new edgeinfo;
edgeinfos.push_back(ei);
ei->i = i; ei->i = i;
ei->j = j; ei->j = j;
ei->weight = wei; ei->weight = wei;
@ -263,7 +266,11 @@ int readLabel(FILE *f) {
return getid(xlabel); return getid(xlabel);
} }
void readAnyGraph(string fn) { namespace anygraph {
double R, alpha, T;
vector<pair<double, double> > coords;
void read(string fn, bool subdiv = true) {
init(); kind = kAnyGraph; init(); kind = kAnyGraph;
FILE *f = fopen((fn + "-coordinates.txt").c_str(), "rt"); FILE *f = fopen((fn + "-coordinates.txt").c_str(), "rt");
if(!f) { if(!f) {
@ -272,11 +279,12 @@ void readAnyGraph(string fn) {
} }
printf("Reading coordinates...\n"); printf("Reading coordinates...\n");
char buf[100]; char buf[100];
double x; int N; int N;
int err; int err;
err = fscanf(f, "%s%s%s%s%d%lf%lf%lf", buf, buf, buf, buf, &N, &x, &x, &x); err = fscanf(f, "%s%s%s%s%d%lf%lf%lf", buf, buf, buf, buf, &N,
&anygraph::R, &anygraph::alpha, &anygraph::T);
if(err < 8) { printf("Error: incorrect format of the first line\n"); exit(1); } if(err < 8) { printf("Error: incorrect format of the first line\n"); exit(1); }
vdata.resize(N); vdata.reserve(N);
while(true) { while(true) {
int id = readLabel(f); int id = readLabel(f);
if(id < 0) break; if(id < 0) break;
@ -286,6 +294,7 @@ void readAnyGraph(string fn) {
double r, alpha; double r, alpha;
int err = fscanf(f, "%lf%lf", &r, &alpha); int err = fscanf(f, "%lf%lf", &r, &alpha);
coords.push_back(make_pair(r, alpha));
if(err < 2) { printf("Error: incorrect format of r/alpha\n"); exit(1); } if(err < 2) { printf("Error: incorrect format of r/alpha\n"); exit(1); }
transmatrix h = spin(alpha * 2 * M_PI / 360) * xpush(r); transmatrix h = spin(alpha * 2 * M_PI / 360) * xpush(r);
@ -304,7 +313,7 @@ void readAnyGraph(string fn) {
while(true) { while(true) {
int i = readLabel(f), j = readLabel(f); int i = readLabel(f), j = readLabel(f);
if(i == -1 || j == -1) break; if(i == -1 || j == -1) break;
addedge(i, j, 0, true); addedge(i, j, 0, subdiv);
if(qlink % 10000 == 0) printf("%d\n", qlink); if(qlink % 10000 == 0) printf("%d\n", qlink);
qlink++; qlink++;
} }
@ -318,6 +327,8 @@ void readAnyGraph(string fn) {
printf("Done.\n"); printf("Done.\n");
} }
}
namespace tree { namespace tree {
struct treevertex { struct treevertex {
@ -1217,6 +1228,9 @@ void close() {
vdata.clear(); vdata.clear();
labeler.clear(); labeler.clear();
legend.clear(); legend.clear();
for(int i=0; i<size(edgeinfos); i++) delete edgeinfos[i];
edgeinfos.clear();
anygraph::coords.clear();
on = false; on = false;
} }
@ -1300,7 +1314,7 @@ int readArgs() {
// this visualizes the data from: https://hpi.de/friedrich/research/hyperbolic // this visualizes the data from: https://hpi.de/friedrich/research/hyperbolic
else if(argis("-graph")) { else if(argis("-graph")) {
PHASE(3); shift(); readAnyGraph(args()); PHASE(3); shift(); anygraph::read(args());
} }
// draw spirals // draw spirals

View File

@ -2,7 +2,7 @@
# set the version numbers in hyper.rc automatically # set the version numbers in hyper.rc automatically
export VER=`grep "#define VER " hyper.cpp | sed "s/#define VER \"//" | sed "s/\"//"` export VER=`grep "#define VER " hyper.cpp | sed "s/#define VER \"//" | sed "s/\"//"`
#export VERNUM=`grep "#define VERNUM " hyper.cpp | sed "s/#define VERNUM //" | sed "s/^\(.\)\(.\)\(.\)\(.\)$/\1.\2.\4.\3/"` #export VERNUM=`grep "#define VERNUM " hyper.cpp | sed "s/#define VERNUM //" | sed "s/^\(.\)\(.\)\(.\)\(.\)$/\1.\2.\4.\3/"`
VERNUM=9,4,0,6 VERNUM=9,4,0,7
#VERNUM=8.1.7.0 #VERNUM=8.1.7.0
#echo $VERNUM #echo $VERNUM
sed "s/\"ProductVersion\", \"\(.*\)\"/\"ProductVersion\", \"$VER\"/" -i hyper.rc sed "s/\"ProductVersion\", \"\(.*\)\"/\"ProductVersion\", \"$VER\"/" -i hyper.rc

View File

@ -3034,11 +3034,16 @@ bool drawMonster(const transmatrix& V, cell *c, const transmatrix*& Vboat, trans
return false; return false;
} }
void clearMemory() { void clearMonsters() {
for(mit it = monstersAt.begin(); it != monstersAt.end(); it++) for(mit it = monstersAt.begin(); it != monstersAt.end(); it++)
delete(it->second); delete(it->second);
for(int i=0; i<size(active); i++) delete active[i]; for(int i=0; i<size(active); i++) delete active[i];
monstersAt.clear(); monstersAt.clear();
active.clear();
}
void clearMemory() {
clearMonsters();
gmatrix.clear(); gmatrix.clear();
curtime = 0; curtime = 0;
nextmove = 0; nextmove = 0;

View File

@ -864,6 +864,7 @@ namespace gamestack {
heptspin viewctr; heptspin viewctr;
transmatrix View; transmatrix View;
eGeometry geometry; eGeometry geometry;
bool shmup;
bool hepta; bool hepta;
}; };
@ -882,6 +883,7 @@ namespace gamestack {
gdn.viewctr = viewctr; gdn.viewctr = viewctr;
gdn.View = View; gdn.View = View;
gdn.geometry = geometry; gdn.geometry = geometry;
gdn.shmup = shmup::on;
gdn.hepta = purehepta; gdn.hepta = purehepta;
gd.push_back(gdn); gd.push_back(gdn);
} }
@ -894,6 +896,8 @@ namespace gamestack {
View = gdn.View; View = gdn.View;
geometry = gdn.geometry; geometry = gdn.geometry;
purehepta = gdn.hepta; purehepta = gdn.hepta;
if(shmup::on) shmup::clearMonsters();
shmup::on = gdn.shmup;
resetGeometry(); resetGeometry();
gd.pop_back(); gd.pop_back();
bfs(); bfs();

205
tour.cpp
View File

@ -1,4 +1,5 @@
// work in progress // Hyperbolic Rogue -- the Tutorial/presentation
// Copyright (C) 2011-2017 Zeno Rogue, see 'hyper.cpp' for details
namespace tour { namespace tour {
@ -10,16 +11,24 @@ string tourhelp;
int currentslide; int currentslide;
static struct { const char *name; int id; const char *help; } slides[] = { #define LEGAL_NONE 0
{"Introduction", 10, #define LEGAL_UNLIMITED 1
#define LEGAL_HYPERBOLIC 2
#define LEGAL_ANY 3
#define LEGAL_NONEUC 4
static struct { const char *name; int id; int legal; const char *help; } slides[] = {
{"Introduction", 10, LEGAL_ANY,
"This tutorial is mostly aimed to show what is " "This tutorial is mostly aimed to show what is "
"special about the geometry used by HyperRogue. " "special about the geometry used by HyperRogue. "
"It also shows the basics of gameplay, and " "It also shows the basics of gameplay, and "
"how is it affected by geometry.\n\n" "how is it affected by geometry.\n\n"
"Press Enter to go to the next slide, or ESC to see a " "You decide when you want to stop playing with the "
"current \"slide\" and go to the next one, by pressing Enter. You can also "
"press ESC to see a "
"menu with other options." "menu with other options."
}, },
{"Basics of gameplay", 11, {"Basics of gameplay", 11, LEGAL_ANY,
"The game starts in the Icy Lands. Collect the Ice Diamonds " "The game starts in the Icy Lands. Collect the Ice Diamonds "
"(press F1 if you do not know how to move). " "(press F1 if you do not know how to move). "
"After you collect many of them, monsters will start to pose a challenge.\n" "After you collect many of them, monsters will start to pose a challenge.\n"
@ -31,14 +40,14 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"wants -- for example, in this slide, you can press '5' to get " "wants -- for example, in this slide, you can press '5' to get "
"lots of Ice Diamonds quickly." "lots of Ice Diamonds quickly."
}, },
{"Hypersian Rug model", 21, {"Hypersian Rug model", 21, LEGAL_HYPERBOLIC,
"New players think that the action of HyperRogue takes place on a sphere. " "New players think that the action of HyperRogue takes place on a sphere. "
"This is not true -- the next slide will show the surface HyperRogue " "This is not true -- the next slide will show the surface HyperRogue "
"actually takes place on.\n\n" "actually takes place on.\n\n"
"Use arrow keys to rotate the model, and Page Up/Down to zoom.\n\n" "Use arrow keys to rotate the model, and Page Up/Down to zoom.\n\n"
"If you do not see anything, press '5' to try a safer renderer." "If you do not see anything, press '5' to try a safer renderer."
}, },
{"Expansion", 22, {"Expansion", 22, LEGAL_ANY,
"The next slide shows the number of cells in distance 1, 2, 3, ... from you. " "The next slide shows the number of cells in distance 1, 2, 3, ... from you. "
"It grows exponentially: there are more than 10^100 cells " "It grows exponentially: there are more than 10^100 cells "
"in radius 1000 around you, and you will move further away during the game!\n\n" "in radius 1000 around you, and you will move further away during the game!\n\n"
@ -52,7 +61,7 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"infinite world. There are almost no permanent upgrades; collecting treasures " "infinite world. There are almost no permanent upgrades; collecting treasures "
"brings you benefits, but trying to get too many of the same kind is extremely dangerous." "brings you benefits, but trying to get too many of the same kind is extremely dangerous."
}, },
{"Tiling and Tactics", 23, {"Tiling and Tactics", 23, LEGAL_ANY,
"The tactics of fighting simple monsters, such as the Yetis from the Icy Lands, " "The tactics of fighting simple monsters, such as the Yetis from the Icy Lands, "
"might appear shallow, but hyperbolic geometry is essential even there. " "might appear shallow, but hyperbolic geometry is essential even there. "
"In the next slide, you are attacked by two monsters at once. " "In the next slide, you are attacked by two monsters at once. "
@ -60,18 +69,21 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"running away in a straight line. " "running away in a straight line. "
"Press '2' to try the same in the Euclidean world -- it is impossible." "Press '2' to try the same in the Euclidean world -- it is impossible."
}, },
{"Straight Lines", 24, {"Straight Lines", 24, LEGAL_ANY,
"Hyperbolic geometry has been created by 19th century mathematicians who " "Hyperbolic geometry has been discovered by the 19th century mathematicians who "
"wondered about the nature of paralellness. Take a line L and a point A. " "wondered about the nature of paralellness. Take a line L and a point A. "
"Can a world exist where there is more than one line passing through A " "Can a world exist where there is more than one line passing through A "
"which does not cross L?\n\n" "which does not cross L?\n\n"
"The Icy Land will be very dangerous if you have lots of Ice Diamonds -- "
"lots of Yetis and Ice Wolves hunting you! But the other lands, where "
"you have no treasures yet, will still be (relatively) safe.\n\n"
"Wander further, and you should find Crossroads quickly -- " "Wander further, and you should find Crossroads quickly -- "
"the Great Walls are straight lines, and indeed, they work differently than in " "the Great Walls are straight lines, and indeed, they work differently than in "
"Euclidean. On the other side of Great Walls, you see other lands -- " "Euclidean. On the other side of Great Walls, you see other lands -- "
"there are about 50 lands in HyperRogue, based " "there are about 50 lands in HyperRogue, based "
"on different mechanics and aspects of hyperbolic geometry." "on different mechanics and aspects of hyperbolic geometry."
}, },
{"Running Dogs", 25, {"Running Dogs", 25, LEGAL_ANY,
"To learn more about straight lines, " "To learn more about straight lines, "
"wander further, and you should find the Land of Eternal Motion. " "wander further, and you should find the Land of Eternal Motion. "
"Try to run in a straight line, with a Running Dog next to you. " "Try to run in a straight line, with a Running Dog next to you. "
@ -80,7 +92,7 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"in a straight line, and the Running Dog has to run in a curve " "in a straight line, and the Running Dog has to run in a curve "
"called an equidistant." "called an equidistant."
}, },
{"Equidistants", 27, {"Equidistants", 27, LEGAL_ANY,
"Equidistants are curves which are at some fixed distance from a " "Equidistants are curves which are at some fixed distance from a "
"straight line. Some lands in HyperRogue are based on equidistants; " "straight line. Some lands in HyperRogue are based on equidistants; "
"you should see them after wandering a bit more.\n\n" "you should see them after wandering a bit more.\n\n"
@ -88,14 +100,14 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"but we do not recommend going deep into the Dungeon or the Ocean -- " "but we do not recommend going deep into the Dungeon or the Ocean -- "
"getting back might be difficult." "getting back might be difficult."
}, },
{"Circles", 26, {"Circles", 26, LEGAL_ANY,
"Circles are strange in hyperbolic geometry too. " "Circles are strange in hyperbolic geometry too. "
"Look for the Castle of Camelot in the Crossroads; " "Look for the Castle of Camelot in the Crossroads; "
"the Round Table inside is a circle of radius 28. " "the Round Table inside is a circle of radius 28. "
"Finding its center is a difficult challenge.\n\n" "Finding its center is a difficult challenge.\n\n"
"Press '5' to cheat by seeing the smaller circles too." "Press '5' to cheat by seeing the smaller circles too."
}, },
{"Horocycles", 28, {"Horocycles", 28, LEGAL_ANY,
"Horocycles are similar to circles, but you cannot reach their center at all -- " "Horocycles are similar to circles, but you cannot reach their center at all -- "
"they can be understood as limit circles of infinite radius centered in some point " "they can be understood as limit circles of infinite radius centered in some point "
"in infinity (also called an ideal point).\n\n" "in infinity (also called an ideal point).\n\n"
@ -103,7 +115,7 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"Each circle of columns is actually a horocycle. Horocycles in a given " "Each circle of columns is actually a horocycle. Horocycles in a given "
"temple are concentric, and there is an infinite number of them." "temple are concentric, and there is an infinite number of them."
}, },
{"Half-plane model", 47, {"Half-plane model", 47, LEGAL_HYPERBOLIC,
"The game is normally displayed in the so called Poincaré disk model, " "The game is normally displayed in the so called Poincaré disk model, "
"which is a kind of a map of the infinite hyperbolic world. " "which is a kind of a map of the infinite hyperbolic world. "
"There are many projections of Earth, but since Earth is curved, " "There are many projections of Earth, but since Earth is curved, "
@ -112,7 +124,7 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"The next slide shows another model, called the Poincaré upper half-plane model. In this model, " "The next slide shows another model, called the Poincaré upper half-plane model. In this model, "
"horocycles centered at one specific ideal point are drawn as straight lines." "horocycles centered at one specific ideal point are drawn as straight lines."
}, },
{"Curvature", 29, {"Curvature", 29, LEGAL_ANY,
"Now, go to the Burial Grounds and find an Orb of the Sword. The Sword appears to " "Now, go to the Burial Grounds and find an Orb of the Sword. The Sword appears to "
"always be facing in the same direction whatever you do, and it appears that " "always be facing in the same direction whatever you do, and it appears that "
"you have to rotate the sword to excavate the treasures; " "you have to rotate the sword to excavate the treasures; "
@ -122,21 +134,21 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"This is related to the fact that the world of HyperRogue is curved, and " "This is related to the fact that the world of HyperRogue is curved, and "
"the sum of angles in a triangle is not equal to 180 degrees." "the sum of angles in a triangle is not equal to 180 degrees."
}, },
{"Periodic patterns", 30, {"Periodic patterns", 30, LEGAL_UNLIMITED,
"Hyperbolic geometry yields much more interesting periodic patterns " "Hyperbolic geometry yields much more interesting periodic patterns "
"than Euclidean." "than Euclidean."
}, },
{"Periodic patterns: application", 31, {"Periodic patterns: application", 31, LEGAL_ANY,
"Many lands in HyperRogue are based around periodic patterns. " "Many lands in HyperRogue are based around periodic patterns. "
"For example, both Zebra and Windy Plains are based on the pattern " "For example, both Zebra and Windy Plains are based on the pattern "
"shown in the previous slide. " "shown in the previous slide. "
"Such lands often have tree-like nature." "Such lands often have tree-like nature."
}, },
{"Fractal landscapes", 32, {"Fractal landscapes", 32, LEGAL_UNLIMITED,
"On the following slide, the colors change smoothly in the whole infinite world. " "On the following slide, the colors change smoothly in the whole infinite world. "
"Again, this works better than in Euclidean geometry." "Again, this works better than in Euclidean geometry."
}, },
{"Fractal landscapes: application", 33, {"Fractal landscapes: application", 33, LEGAL_ANY,
"This is applied in HyperRogue to create landscapes, such as the chasms in the " "This is applied in HyperRogue to create landscapes, such as the chasms in the "
"land of Reptiles or the Dragon Chasms, which you should find quickly. " "land of Reptiles or the Dragon Chasms, which you should find quickly. "
"Also in the Dragon Chasms, you can find a Baby Tortoise, and try to find " "Also in the Dragon Chasms, you can find a Baby Tortoise, and try to find "
@ -146,7 +158,7 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"the color in Galápagos is, the more aspects of the tortoises in the given " "the color in Galápagos is, the more aspects of the tortoises in the given "
"area are matching." "area are matching."
}, },
{"Poincaré Ball model", 41, {"Poincaré Ball model", 41, LEGAL_HYPERBOLIC,
"The Poincaré disk model is a model of a hyperbolic *plane* -- you " "The Poincaré disk model is a model of a hyperbolic *plane* -- you "
"might wonder why are the walls rendered in 3D then.\n\n" "might wonder why are the walls rendered in 3D then.\n\n"
"HyperRogue actually assumes that the floor level is an equidistant surface " "HyperRogue actually assumes that the floor level is an equidistant surface "
@ -156,21 +168,21 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"This is shown on the next slide, in the Poincaré ball model, which is " "This is shown on the next slide, in the Poincaré ball model, which is "
"the 3D analog of the Poincaré disk model." "the 3D analog of the Poincaré disk model."
}, },
{"Hyperboloid model", 42, {"Hyperboloid model", 42, LEGAL_ANY,
"Let's see more models of the hyperbolic plane. " "Let's see more models of the hyperbolic plane. "
"This model uses a hyperboloid in the Minkowski geometry; " "This model uses a hyperboloid in the Minkowski geometry; "
"it is used internally by HyperRogue." "it is used internally by HyperRogue."
}, },
{"Beltrami-Klein model", 43, {"Beltrami-Klein model", 43, LEGAL_ANY,
"This model renders straight lines as straight, but it distorts angles." "This model renders straight lines as straight, but it distorts angles."
}, },
{"Gans model", 44, {"Gans model", 44, LEGAL_ANY,
"Yet another model, which corresponds to orthographic projection of the " "Yet another model, which corresponds to orthographic projection of the "
"sphere. Poincaré disk model, Beltrami-Klein model, and the Gans " "sphere. Poincaré disk model, Beltrami-Klein model, and the Gans "
"model are all obtained by looking at either the hyperboloid model or an " "model are all obtained by looking at either the hyperboloid model or an "
"equidistant surface from various distances." "equidistant surface from various distances."
}, },
{"Band model", 45, {"Band model", 45, LEGAL_NONEUC,
"The band model is the hyperbolic analog of the Mercator projection of the sphere: " "The band model is the hyperbolic analog of the Mercator projection of the sphere: "
"a given straight line is rendered as a straight line, and the rest of the " "a given straight line is rendered as a straight line, and the rest of the "
"world is mapped conformally, that is, angles are not distorted. " "world is mapped conformally, that is, angles are not distorted. "
@ -180,11 +192,11 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"If you want, press '5' to see it rendered as a spiral, although it takes lots of time and " "If you want, press '5' to see it rendered as a spiral, although it takes lots of time and "
"memory." "memory."
}, },
{"Conformal square model", 46, {"Conformal square model", 46, LEGAL_HYPERBOLIC,
"The world can be mapped conformally to a square too." "The world can be mapped conformally to a square too."
}, },
#ifdef ROGUEVIZ #ifdef ROGUEVIZ
{"Collatz conjecture", 51, {"Collatz conjecture", 51, LEGAL_NONE,
"Your version of HyperRogue includes RogueViz, which " "Your version of HyperRogue includes RogueViz, which "
"is an adaptation of HyperRogue as a visualization tool " "is an adaptation of HyperRogue as a visualization tool "
"rather than a game. Hyperbolic space is great " "rather than a game. Hyperbolic space is great "
@ -193,9 +205,17 @@ static struct { const char *name; int id; const char *help; } slides[] = {
"The following slide is a visualization of the Collatz conjecture. " "The following slide is a visualization of the Collatz conjecture. "
"Press '5' for a spiral rendering of the Collatz conjecture visualization."}, "Press '5' for a spiral rendering of the Collatz conjecture visualization."},
#endif #endif
{"THE END", 99, {"Shoot'em up mode", 52, LEGAL_NONE,
"This is not everything you can see in HyperRogue. For example, " "In the shoot'em up mode, space and time is continuous. "
"hyperbolic mazes are much fun than their Euclidean counterparts. " "You attack by throwing knives. "
"Very fun with two players!\n\n"
"There are other special modes too which change the gameplay or "
"focus on a particular challenge."
},
{"THE END", 99, LEGAL_ANY,
"This tour shows just a small part of what you can see in the world of HyperRogue. "
"For example, "
"hyperbolic mazes are much nicer than their Euclidean counterparts. "
"Have fun exploring!\n\n" "Have fun exploring!\n\n"
"Press '5' to leave the tutorial mode." "Press '5' to leave the tutorial mode."
} }
@ -278,6 +298,7 @@ void presentation(int mode) {
if(id == 22) { if(id == 22) {
if(mode == 1) viewdists = true; if(mode == 1) viewdists = true;
if(mode == 2) viewdists = canmove; // disable when killed
if(mode == 3) viewdists = false; if(mode == 3) viewdists = false;
} }
@ -348,6 +369,7 @@ void presentation(int mode) {
resetview(); resetview();
drawthemap(); drawthemap();
centerpc(INF); centerpc(INF);
conformal::includeHistory = false;
} }
if(mode == 4) conformal::createImage(true); if(mode == 4) conformal::createImage(true);
} }
@ -386,6 +408,11 @@ void presentation(int mode) {
rogueviz::collatz::start(); rogueviz::collatz::start();
} }
if(mode == 3) {
rogueviz::close();
shmup::clearMonsters();
}
if(mode == 4) if(mode == 4)
pmodel = mdBand, conformal::create(), conformal::rotation = 0, pmodel = mdBand, conformal::create(), conformal::rotation = 0,
conformal::createImage(true), conformal::createImage(true),
@ -394,6 +421,16 @@ void presentation(int mode) {
#endif #endif
if(id == 52 && mode == 1) {
firstland = cwt.c->land;
restartGame('s', true);
}
if(id == 52 && mode == 3) {
shmup::clearMonsters();
restartGame(0, false);
}
if(id == 99 && mode == 4) if(id == 99 && mode == 4)
restartGame('T'); restartGame('T');
} }
@ -487,7 +524,7 @@ void slidehelp() {
bool handleKeyTour(int sym, int uni) { bool handleKeyTour(int sym, int uni) {
if(sym == SDLK_RETURN && (cmode != emHelp || getid() == 10)) { if(sym == SDLK_RETURN && (cmode != emHelp || getid() == 10)) {
if(geometry) { restartGame(0, false); return true; } if(geometry || purehepta) { restartGame(0, false); return true; }
if(getid() == 99) return true; if(getid() == 99) return true;
presentation(3); presentation(3);
currentslide++; currentslide++;
@ -496,7 +533,7 @@ bool handleKeyTour(int sym, int uni) {
return true; return true;
} }
if(sym == SDLK_BACKSPACE) { if(sym == SDLK_BACKSPACE) {
if(geometry) { restartGame(0, false); return true; } if(geometry || purehepta) { restartGame(0, false); return true; }
if(currentslide == 0) { slidehelp(); return true; } if(currentslide == 0) { slidehelp(); return true; }
presentation(3); presentation(3);
currentslide--; currentslide--;
@ -505,9 +542,51 @@ bool handleKeyTour(int sym, int uni) {
return true; return true;
} }
if(sym == '1' || sym == '2' || sym == '3') { if(sym == '1' || sym == '2' || sym == '3') {
if(geometry) { int legal = slides[currentslide].legal;
restartGame(0, false); return true;
if(legal == 0) {
addMessage(XLAT("You cannot change geometry in this slide."));
return true;
} }
if(legal == 1 && sym == '1') {
addMessage(XLAT("This does not work in bounded geometries."));
return true;
}
if(legal == 4 && sym == '2') {
addMessage(XLAT("This does not work in Euclidean geometry."));
return true;
}
if(legal == 2 && sym != '3') {
addMessage(XLAT("This works only in hyperbolic geometry."));
return true;
}
if(sym == '2') {
bool ok = cwt.c->land == laCanvas;
for(int i=0; i<LAND_EUC; i++) if(land_euc[i] == cwt.c->land) ok = true;
if(!ok) {
addMessage(XLAT("This land has no Euclidean version."));
return true;
}
}
if(sym == '1') {
bool ok = cwt.c->land == laCanvas;
for(int i=0; i<LAND_SPH; i++) if(land_sph[i] == cwt.c->land) ok = true;
if(!ok) {
addMessage(XLAT("This land has no spherical version."));
return true;
}
}
if(geometry || purehepta) {
restartGame(0, false);
if(getid() == 45) conformal::create();
return true;
}
if(getid() == 45) conformal::clear();
if(sym == '1') targetgeometry = gSphere; if(sym == '1') targetgeometry = gSphere;
if(sym == '2') targetgeometry = gEuclid; if(sym == '2') targetgeometry = gEuclid;
firstland = euclidland = cwt.c->land; firstland = euclidland = cwt.c->land;
@ -515,8 +594,21 @@ bool handleKeyTour(int sym, int uni) {
return true; return true;
} }
if(sym == '4') { if(sym == '4') {
cmode = emNormal;
if(items[itOrbTeleport]) goto give_aether;
items[itOrbTeleport] = 1; items[itOrbTeleport] = 1;
checkmove();
if(!canmove) {
if(items[itOrbAether]) goto give_flash;
give_aether:
items[itOrbAether] = 10;
checkmove();
if(!canmove) {
give_flash:
activateFlash();
canmove = true; canmove = true;
}
}
return true; return true;
} }
if(sym == '5') { if(sym == '5') {
@ -542,8 +634,10 @@ bool handleKeyTour(int sym, int uni) {
else addMessage("Help texts disabled."); else addMessage("Help texts disabled.");
return true; return true;
} }
if(sym == '8') if(sym == '8') {
conformal::includeHistory = !conformal::includeHistory; conformal::includeHistory = !conformal::includeHistory;
return true;
}
return false; return false;
} }
@ -556,6 +650,47 @@ bool quickfind(eLand l) {
return false; return false;
} }
bool showland(eLand l) {
int id = getid();
if(id == 10 || id == 11) return l == laIce;
if(id == 21 || id == 22) return l == laIce;
if(id == 23) return l == laCanvas;
if(id == 24) return l == laCrossroads || l == laIce;
if(id == 25) return l == laCrossroads || l == laMotion;
if(id == 26) return l == laCrossroads || l == laCamelot;
if(id == 27)
return l == laCrossroads || l == laDungeon || l == laOcean || l == laIvoryTower || l == laEndorian;
if(id == 28)
return l == laCrossroads || l == laRlyeh || l == laTemple;
if(id == 29)
return l == laCrossroads || l == laBurial;
if(id == 30) return l == laCanvas;
if(id == 31)
return
l == laCrossroads ||
l == laZebra || l == laWhirlwind || l == laPalace || l == laPrairie ||
l == laEmerald || l == laWineyard || l == laPower;
if(id == 32) return l == laCanvas;
if(id == 33)
return l == laCrossroads || l == laReptile || l == laDragon || l == laTortoise;
return true;
}
void checkGoodLand(eLand l) {
if(!showland(l) && texts) {
help = XLAT(
"This tutorial is different than most other game tutorials -- "
"you are not forced to do anything, and you can go wherever you want.\n\n"
"However, %the1 is not what we are talking about now. "
"We will not explain this land at the moment, and you could ponentially "
"get lost there.\n\n"
"Remember that you can get to the next slide by pressing Enter.",
l
);
cmode = emHelp;
}
}
void start() { void start() {
currentslide = 0; currentslide = 0;
vid.scale = 1; vid.scale = 1;

View File

@ -789,7 +789,7 @@ int newmodecode = 254;
int modecode() { int modecode() {
#ifndef NOSAVE #ifndef NOSAVE
if(anticheat::tampered || cheater) return 6; if(anticheat::tampered || cheater || tour::on) return 6;
if(quotient) return 6; if(quotient) return 6;
#endif #endif
int xcode = 0; int xcode = 0;