mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-12-21 05:18:05 +00:00
Updated to 9.4g (mostly tutorial fixes)
This commit is contained in:
207
tour.cpp
207
tour.cpp
@@ -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 {
|
||||
|
||||
@@ -10,16 +11,24 @@ string tourhelp;
|
||||
|
||||
int currentslide;
|
||||
|
||||
static struct { const char *name; int id; const char *help; } slides[] = {
|
||||
{"Introduction", 10,
|
||||
#define LEGAL_NONE 0
|
||||
#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 "
|
||||
"special about the geometry used by HyperRogue. "
|
||||
"It also shows the basics of gameplay, and "
|
||||
"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."
|
||||
},
|
||||
{"Basics of gameplay", 11,
|
||||
{"Basics of gameplay", 11, LEGAL_ANY,
|
||||
"The game starts in the Icy Lands. Collect the Ice Diamonds "
|
||||
"(press F1 if you do not know how to move). "
|
||||
"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 "
|
||||
"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. "
|
||||
"This is not true -- the next slide will show the surface HyperRogue "
|
||||
"actually takes place on.\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."
|
||||
},
|
||||
{"Expansion", 22,
|
||||
{"Expansion", 22, LEGAL_ANY,
|
||||
"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 "
|
||||
"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 "
|
||||
"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, "
|
||||
"might appear shallow, but hyperbolic geometry is essential even there. "
|
||||
"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. "
|
||||
"Press '2' to try the same in the Euclidean world -- it is impossible."
|
||||
},
|
||||
{"Straight Lines", 24,
|
||||
"Hyperbolic geometry has been created by 19th century mathematicians who "
|
||||
{"Straight Lines", 24, LEGAL_ANY,
|
||||
"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. "
|
||||
"Can a world exist where there is more than one line passing through A "
|
||||
"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 -- "
|
||||
"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 -- "
|
||||
"there are about 50 lands in HyperRogue, based "
|
||||
"on different mechanics and aspects of hyperbolic geometry."
|
||||
},
|
||||
{"Running Dogs", 25,
|
||||
{"Running Dogs", 25, LEGAL_ANY,
|
||||
"To learn more about straight lines, "
|
||||
"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. "
|
||||
@@ -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 "
|
||||
"called an equidistant."
|
||||
},
|
||||
{"Equidistants", 27,
|
||||
{"Equidistants", 27, LEGAL_ANY,
|
||||
"Equidistants are curves which are at some fixed distance from a "
|
||||
"straight line. Some lands in HyperRogue are based on equidistants; "
|
||||
"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 -- "
|
||||
"getting back might be difficult."
|
||||
},
|
||||
{"Circles", 26,
|
||||
{"Circles", 26, LEGAL_ANY,
|
||||
"Circles are strange in hyperbolic geometry too. "
|
||||
"Look for the Castle of Camelot in the Crossroads; "
|
||||
"the Round Table inside is a circle of radius 28. "
|
||||
"Finding its center is a difficult challenge.\n\n"
|
||||
"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 -- "
|
||||
"they can be understood as limit circles of infinite radius centered in some point "
|
||||
"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 "
|
||||
"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, "
|
||||
"which is a kind of a map of the infinite hyperbolic world. "
|
||||
"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, "
|
||||
"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 "
|
||||
"always be facing in the same direction whatever you do, and it appears that "
|
||||
"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 "
|
||||
"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 "
|
||||
"than Euclidean."
|
||||
},
|
||||
{"Periodic patterns: application", 31,
|
||||
{"Periodic patterns: application", 31, LEGAL_ANY,
|
||||
"Many lands in HyperRogue are based around periodic patterns. "
|
||||
"For example, both Zebra and Windy Plains are based on the pattern "
|
||||
"shown in the previous slide. "
|
||||
"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. "
|
||||
"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 "
|
||||
"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 "
|
||||
@@ -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 "
|
||||
"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 "
|
||||
"might wonder why are the walls rendered in 3D then.\n\n"
|
||||
"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 "
|
||||
"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. "
|
||||
"This model uses a hyperboloid in the Minkowski geometry; "
|
||||
"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."
|
||||
},
|
||||
{"Gans model", 44,
|
||||
{"Gans model", 44, LEGAL_ANY,
|
||||
"Yet another model, which corresponds to orthographic projection of the "
|
||||
"sphere. Poincaré disk model, Beltrami-Klein model, and the Gans "
|
||||
"model are all obtained by looking at either the hyperboloid model or an "
|
||||
"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: "
|
||||
"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. "
|
||||
@@ -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 "
|
||||
"memory."
|
||||
},
|
||||
{"Conformal square model", 46,
|
||||
{"Conformal square model", 46, LEGAL_HYPERBOLIC,
|
||||
"The world can be mapped conformally to a square too."
|
||||
},
|
||||
#ifdef ROGUEVIZ
|
||||
{"Collatz conjecture", 51,
|
||||
{"Collatz conjecture", 51, LEGAL_NONE,
|
||||
"Your version of HyperRogue includes RogueViz, which "
|
||||
"is an adaptation of HyperRogue as a visualization tool "
|
||||
"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. "
|
||||
"Press '5' for a spiral rendering of the Collatz conjecture visualization."},
|
||||
#endif
|
||||
{"THE END", 99,
|
||||
"This is not everything you can see in HyperRogue. For example, "
|
||||
"hyperbolic mazes are much fun than their Euclidean counterparts. "
|
||||
{"Shoot'em up mode", 52, LEGAL_NONE,
|
||||
"In the shoot'em up mode, space and time is continuous. "
|
||||
"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"
|
||||
"Press '5' to leave the tutorial mode."
|
||||
}
|
||||
@@ -278,6 +298,7 @@ void presentation(int mode) {
|
||||
|
||||
if(id == 22) {
|
||||
if(mode == 1) viewdists = true;
|
||||
if(mode == 2) viewdists = canmove; // disable when killed
|
||||
if(mode == 3) viewdists = false;
|
||||
}
|
||||
|
||||
@@ -348,6 +369,7 @@ void presentation(int mode) {
|
||||
resetview();
|
||||
drawthemap();
|
||||
centerpc(INF);
|
||||
conformal::includeHistory = false;
|
||||
}
|
||||
if(mode == 4) conformal::createImage(true);
|
||||
}
|
||||
@@ -385,6 +407,11 @@ void presentation(int mode) {
|
||||
|
||||
rogueviz::collatz::start();
|
||||
}
|
||||
|
||||
if(mode == 3) {
|
||||
rogueviz::close();
|
||||
shmup::clearMonsters();
|
||||
}
|
||||
|
||||
if(mode == 4)
|
||||
pmodel = mdBand, conformal::create(), conformal::rotation = 0,
|
||||
@@ -394,6 +421,16 @@ void presentation(int mode) {
|
||||
|
||||
#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)
|
||||
restartGame('T');
|
||||
}
|
||||
@@ -487,7 +524,7 @@ void slidehelp() {
|
||||
|
||||
bool handleKeyTour(int sym, int uni) {
|
||||
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;
|
||||
presentation(3);
|
||||
currentslide++;
|
||||
@@ -496,7 +533,7 @@ bool handleKeyTour(int sym, int uni) {
|
||||
return true;
|
||||
}
|
||||
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; }
|
||||
presentation(3);
|
||||
currentslide--;
|
||||
@@ -505,9 +542,51 @@ bool handleKeyTour(int sym, int uni) {
|
||||
return true;
|
||||
}
|
||||
if(sym == '1' || sym == '2' || sym == '3') {
|
||||
if(geometry) {
|
||||
restartGame(0, false); return true;
|
||||
int legal = slides[currentslide].legal;
|
||||
|
||||
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 == '2') targetgeometry = gEuclid;
|
||||
firstland = euclidland = cwt.c->land;
|
||||
@@ -515,8 +594,21 @@ bool handleKeyTour(int sym, int uni) {
|
||||
return true;
|
||||
}
|
||||
if(sym == '4') {
|
||||
cmode = emNormal;
|
||||
if(items[itOrbTeleport]) goto give_aether;
|
||||
items[itOrbTeleport] = 1;
|
||||
canmove = true;
|
||||
checkmove();
|
||||
if(!canmove) {
|
||||
if(items[itOrbAether]) goto give_flash;
|
||||
give_aether:
|
||||
items[itOrbAether] = 10;
|
||||
checkmove();
|
||||
if(!canmove) {
|
||||
give_flash:
|
||||
activateFlash();
|
||||
canmove = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(sym == '5') {
|
||||
@@ -542,8 +634,10 @@ bool handleKeyTour(int sym, int uni) {
|
||||
else addMessage("Help texts disabled.");
|
||||
return true;
|
||||
}
|
||||
if(sym == '8')
|
||||
if(sym == '8') {
|
||||
conformal::includeHistory = !conformal::includeHistory;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -556,6 +650,47 @@ bool quickfind(eLand l) {
|
||||
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() {
|
||||
currentslide = 0;
|
||||
vid.scale = 1;
|
||||
|
||||
Reference in New Issue
Block a user