This commit is contained in:
Zeno Rogue 2017-08-06 14:50:16 +02:00
parent 4f2af2f2c4
commit 130fefa4c4
35 changed files with 24968 additions and 1130 deletions

View File

@ -536,7 +536,7 @@ void achievement_final(bool really_final) {
return;
}
if(sphere && euclidland == laHalloween) {
if(sphere && specialland == laHalloween) {
if(shmup::on || chaosmode || purehepta || numplayers() > 1 || tactic::on || randomPatternsMode)
return;
achievement_score(LB_HALLOWEEN, items[itTreat]);

View File

@ -967,7 +967,7 @@ void setvideomode() {
if(vid.antialias & AA_MULTI) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (vid.antialias & AA_MULTI16) ? 16 : 4);
}
}

View File

@ -1773,3 +1773,61 @@
- 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
2017.07.24 01:49 version 10.0d
- the bottom line in the inventory mode is now always visible (i.e. you can exit the inventory with mouse)
- peaceful mode and shmup mode are now compatible
- fixed the problems with free Orbs of Safety in the Orb Strategy mode
- fixed some texts
2017.07.25 03:21 version 10.0e
- more fixes for the peaceful mode: tortoises no longer move in shmup; Fire Cultists
no longer throw fire; Ivy no longer grows; no more statues under Ivy; no more
Grimoires; the Knights no longer talk about war; the Princess no longer wants
revenge; the Sword is graphically replaced with a shovel and digs again
- fixed a bug with loading the old style config (affected the mobile versions)
- fixed the arrow keys to scroll
- the Android version should no longer draw the screen while locked
- victory speedrun leaderboards in orb strategy
- Narcissist and Mirror Spirit kills count
2017.07.25 21:24 version 10.0f
- color saving on 32bit machines should be fixed
- 'save config' appears again in the basic config
2017.08.06 14:00 version 10.0g
- added a new Yendor Challenge
- improved the efficiency in the Hall of Mirrors
- reduced the sulphur lakes in the Heptagonal Hell
- new princess messages
- Halloween and Reflection should no longer appear in the Chaos Yendor Challenge
- OoY now automatically activates if you move the boat into it
- no more 'you have found ...' spam while moving an object with a boat
- checkmate rule no longer thinks you are protected when standing on top of OoY
- fixed bugs with (hardcore) turn-based multiplayer
- bugfix: Dragon Chasm->Reptiles did not respect the Elixir of Life requirement
- no longer crash on saving peacemode
- map/vector editor commands now always fit on the screen
- [ui] translations updated, languages selectable from a menu
- [ui] new start menu
- [ui] the X for Yendor/Compass is now placed perfectly (well, on the same pixel, and not in Euclidean) and has an aura effect
- [ui] mouse now acts on click, not on release (configurable in the menu)
- [ui] animate legs in char select
- [ui] subtle animations in the inventory/kill list when a monster is killed
- [ui] player death animations in the hardcore mode
- [osm] fixed a bug with mirroring message
- [osm] fixed a bug with Dead Orbs gained incorrectly
- [osm] rewards for extra Daisies and Elemental Gems
- [osm] messages after 25 PF, DDaisies
- [osm] the inventory screen now displays more information
- [osm] dead orbs no longer require Graveyard in the OSM -- more logical that way
- [osm] command line options added for OSM and peace
- [osm] improve centering the orb display
- [cheat] new cheats: save princess, unlock all touched Orbs of Yendor
- [cheat] 'F' clears the "killed by spilling slime carelessly" status
- [cheat] removed cheats that are made redundant by the Map Editor
- [cheat] a special screen for debugging the land generation (cheat: shift+G)
- [mobile] remove menu 'button' from mobiles
- [mobile] the Tutorial is somewhat adjusted for mobiles
- [mobile] map/vector editor available (though not very convenient)

View File

@ -670,7 +670,7 @@ namespace princess {
playSound(c, princessgender() ? "speak-princess" : "speak-prince");
retry:
if(msgid >= 32) msgid = 0;
if(msgid >= 127) msgid = 0;
bool inpalace = c->land == laPalace || c->land == laDungeon;
@ -692,15 +692,36 @@ namespace princess {
else if(msgid == 4 && !inpalace && m == moPrincess && !peace::on) {
addMessage(XLAT("\"I have been trained to fight with a Hypersian scimitar, you know?\"", m));
}
else if(msgid == 5 && !inpalace) {
else if(msgid == 16 && !inpalace) {
addMessage(XLAT("\"I would love to come to your world with you!\"", m));
}
else if(msgid == 6 && !inpalace) {
else if(msgid == 20 && !inpalace) {
addMessage(XLAT("\"I do not like butterflies. They are treacherous.\"", m));
}
else if(msgid == 32 && !inpalace) {
addMessage(XLAT("\"Straight lines stay close to each other forever, this is so romantic!\"", m));
}
else if(msgid == 7 && !inpalace) {
else if(msgid == 40 && !inpalace) {
addMessage(XLAT("\"I hate roses.\"", m));
}
else if(msgid == 48 && !inpalace) {
addMessage(XLAT("\"Maps... Just like the world, but smaller... how is that even possible?!\"", m));
}
else if(msgid == 64) {
addMessage(XLAT("\"In this world there is plenty of space for everyone. We do not need wars.\"", m));
}
else if(msgid == 65) {
addMessage(XLAT("\"Only the stupid hyperbugs do not understand this.\"", m));
}
else if(msgid == 72 && !inpalace) {
addMessage(XLAT("\"I have once talked to a Yendorian researcher... he was only interested in infinite trees.\"", m));
}
else if(msgid == 73 && !inpalace) {
addMessage(XLAT("\"Infinite trees are boring. I prefer other graphs.\"", m));
}
else if(msgid == 80) {
addMessage(XLAT("\"Are there Temples of Cthulhu in your world? Why not?\"", m));
}
else {
msgid++; goto retry;
}
@ -1126,6 +1147,7 @@ namespace mirror {
}
void createHere(cellwalker cw, int cpid) {
if(!cw.c) return;
if(cw.c->wall == waCloud)
createMirages(cw, cpid);
if(cw.c->wall == waMirror)
@ -1133,6 +1155,7 @@ namespace mirror {
}
void breakMirror(cellwalker cw, int pid) {
if(!cw.c) return;
cell *c = cw.c;
if(c->wall == waMirror || c->wall == waCloud) {
drawParticles(c, winf[c->wall].color, 16);
@ -1255,8 +1278,11 @@ namespace mirror {
}
return make_pair(goout, cw);
}
int depth(cell *c) { return c->landparam & 255; }
cellwalker reflect(cellwalker cw, bool debug) {
cellwalker reflect0(cell *c) {
cellwalker cw(c, 0, false);
int stepcount = 0;
cellwalker cwcopy = cw;
static vector<int> v;
@ -1264,18 +1290,15 @@ namespace mirror {
while(true) {
if(!inmirror(cw)) break;
stepcount++; if(stepcount > 10000) {
if(debug) cw.c->wall = waBoat;
if(debug) printf("fail\n");
return cw;
}
cell *c0 = cwpeek(cw, 0);
int go = 0;
if(!inmirror(c0)) go = 2;
else if(c0->landparam && c0->landparam < cw.c->landparam) go = 1;
else if(depth(c0) && depth(c0) < depth(cw.c)) go = 1;
if(go) {
v.push_back(0);
cwstep(cw);
if(debug) queuemarkerat(gmatrix[cw.c], 0x00FF0020);
if(go == 2) break;
}
else {
@ -1299,7 +1322,6 @@ namespace mirror {
cwspin(cw, 2);
v.push_back(2);
cwstep(cw);
if(debug) queuemarkerat(gmatrix[cw.c], 0xC9C90080);
v.push_back(0);
cwspin(cw, 3);
v.push_back(3);
@ -1342,19 +1364,33 @@ namespace mirror {
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);
static const int CACHESIZE = 1<<12; // must be a power of 2
static const int CACHEMASK = CACHESIZE-1;
pair<cell*, cellwalker> cache[CACHESIZE];
int nextcache;
void clearcache() {
for(int i=0; i<CACHESIZE; i++) cache[i].first = NULL;
}
#endif
cellwalker reflect(const cellwalker& cw) {
if(!cw.c) return cw;
int cid = (cw.c->landparam >> 8) & CACHEMASK;
if(cache[cid].first != cw.c) {
cid = nextcache++;
nextcache &= CACHEMASK;
cw.c->landparam &= ~ (CACHEMASK << 8);
cw.c->landparam |= (nextcache << 8);
cache[cid].first = cw.c;
cache[cid].second = reflect0(cw.c);
}
cellwalker res = cache[cid].second;
cwspin(res, cw.spin);
if(cw.mirrored) res.mirrored = !res.mirrored;
return res;
}
}
namespace hive {
@ -2938,5 +2974,6 @@ auto ccm = addHook(clearmemory, 0, [] () {
prairie::enter = NULL;
prairie::tchoices.clear();
prairie::beaststogen.clear();
mirror::clearcache();
});

View File

@ -1,8 +1,14 @@
videopar vid;
charstyle& getcs() {
if(multi::players>1 && multi::cpid >= 0 && multi::cpid < multi::players)
return multi::scs[multi::cpid];
#if ISANDROID
#define ANDROID_SETTINGS settingsChanged = true;
#else
#define ANDROID_SETTINGS ;
#endif
charstyle& getcs(int id) {
if(multi::players>1 && id >= 0 && id < multi::players)
return multi::scs[id];
else
return vid.cs;
}
@ -114,7 +120,7 @@ template<> struct saver<bool> : dsaver<bool> {
template<> struct saver<unsigned> : dsaver<unsigned> {
saver<unsigned>(unsigned& val) : dsaver<unsigned>(val) { }
string save() { return itsh(val); }
void load(const string& s) { val = strtol(s.c_str(), NULL, 16); }
void load(const string& s) { val = (unsigned) strtoll(s.c_str(), NULL, 16); }
};
template<> struct saver<ld> : dsaver<ld> {
@ -272,20 +278,27 @@ void initConfig() {
vid.killreduction = 0;
addsaver(vid.skipstart, "skip the start menu", false);
addsaver(vid.quickmouse, "quick mouse", !ISPANDORA);
// colors
addsaver(backcolor, "color:background");
addsaver(forecolor, "color:foreground");
addsaver(bordcolor, "color:borders");
// modes
addsaverenum(geometry, "mode-geometry");
addsaverenum(euclidland, "mode-geometry land");
addsaver(shmup::on, "mode-shmup", false);
addsaver(hardcore, "mode-hardcore", false);
addsaver(chaosmode, "mode-chaos");
addsaver(inv::on, "mode-Orb Strategy");
addsaver(purehepta, "mode-heptagonal", false);
addsaver(peace::on, "mode-peace");
addsaver(peace::otherpuzzles, "mode-peace-submode");
addsaverenum(specialland, "land for special modes");
addsaver(backcolor, "color:background");
addsaver(forecolor, "color:foreground");
addsaver(bordcolor, "color:borders");
addsaver(viewdists, "expansion mode");
shmup::initConfig();
@ -378,9 +391,9 @@ void loadOldConfig(FILE *f) {
err=fscanf(f, "%d%d", &aa, &bb);
vid.darkhepta = aa; vid.shifttarget = bb;
aa = geometry; bb = euclidland; cc = shmup::on; dd = hardcore;
aa = geometry; bb = specialland; cc = shmup::on; dd = hardcore;
err=fscanf(f, "%d%d%d%d", &aa, &bb, &cc, &dd);
geometry = eGeometry(aa); euclidland = eLand(bb); shmup::on = cc; hardcore = dd;
geometry = eGeometry(aa); specialland = eLand(bb); shmup::on = cc; hardcore = dd;
shmup::loadConfig(f);
@ -526,7 +539,7 @@ void handleAllConfig(int sym, int uni) {
void showGraphConfig() {
gamescreen(0);
cmode = sm::SIDE;
cmode = vid.xres > vid.yres * 1.4 ? sm::SIDE : 0;
dialog::init(XLAT("graphics configuration"));
@ -683,7 +696,7 @@ void switchFullscreen() {
vid.full = !vid.full;
#if ISANDROID
addMessage(XLAT("Reenter HyperRogue to apply this setting"));
settingsChanged = true;
ANDROID_SETTINGS
#endif
#if CAP_SDL
if(true) {
@ -700,9 +713,8 @@ void switchGL() {
vid.usingGL = !vid.usingGL;
if(vid.usingGL) addMessage(XLAT("openGL mode enabled"));
if(!vid.usingGL) addMessage(XLAT("openGL mode disabled"));
#if ISANDROID
settingsChanged = true;
#elif CAP_SDL
ANDROID_SETTINGS;
#if CAP_SDL
setvideomode();
#endif
}
@ -742,24 +754,17 @@ void showBasicConfig() {
dialog::addBoolItem(XLAT("send scores to Steam leaderboards"), (vid.steamscore&1), 'l');
#endif
dialog::addBoolItem(XLAT("skip the start menu"), vid.skipstart, 'm');
#if !ISMOBILE
dialog::addBoolItem(XLAT("quick mouse"), vid.quickmouse, 'M');
#endif
if(CAP_SHMUP && !ISMOBILE)
dialog::addSelItem(XLAT("configure keys/joysticks"), "", 'p');
dialog::addItem(XLAT("reset all configuration"), 'R');
showAllConfig();
if(lang() != 0) {
string tw = "";
string s = XLAT("TRANSLATIONWARNING");
if(s != "" && s != "TRANSLATIONWARNING") tw += s;
s = XLAT("TRANSLATIONWARNING2");
if(s != "" && s != "TRANSLATIONWARNING2") { if(tw != "") tw += " "; tw += s; }
if(tw != "") {
dialog::addBreak(50);
dialog::addHelp(tw);
dialog::lastItem().color = 0xFF0000;
}
}
dialog::display();
keyhandler = [] (int sym, int uni) {
@ -768,6 +773,9 @@ void showBasicConfig() {
char xuni = uni | 96;
if(uni >= 32 && uni < 64) xuni = uni;
if(uni == 'M') vid.quickmouse = !vid.quickmouse;
else if(xuni == 'm') vid.skipstart = !vid.skipstart;
if(xuni == 'c') { vid.axes += 60 + (shiftmul > 0 ? 1 : -1); vid.axes %= 5; }
@ -778,14 +786,8 @@ void showBasicConfig() {
dialog::editNumber(effvolume, 0, 128, 10, 60, XLAT("sound effects volume"), "");
}
if(CAP_TRANS && xuni == 'l') {
vid.language += (shiftmul>0?1:-1);
vid.language %= NUMLAN;
if(vid.language < 0) vid.language += NUMLAN;
#if ISANDROID
settingsChanged = true;
#endif
}
if(CAP_TRANS && xuni == 'l')
pushScreen(selectLanguageScreen);
if(xuni == 'g') pushScreen(showCustomizeChar);
@ -1059,7 +1061,14 @@ void switchcolor(unsigned int& c, unsigned int* cs) {
dialog::openColorDialog(c, cs);
}
double cc_footphase;
int lmousex, lmousey;
void showCustomizeChar() {
cc_footphase += hypot(mousex - lmousex, mousey - lmousey);
lmousex = mousex; lmousey = mousey;
gamescreen(4);
dialog::init(XLAT("Customize character"));
@ -1087,12 +1096,13 @@ void showCustomizeChar() {
dialog::display();
int firsty = dialog::items[0].position / 2;
int scale = firsty - 2 * vid.fsize;
initquickqueue();
transmatrix V = atscreenpos(vid.xres/2, firsty, firsty - 2 * vid.fsize);
transmatrix V = atscreenpos(vid.xres/2, firsty, scale);
double alpha = atan2(mousex - vid.xres/2, mousey - firsty) - M_PI/2;
drawMonsterType(moPlayer, NULL, V * spin(alpha), 0, 0);
drawMonsterType(moPlayer, NULL, V * spin(alpha), 0, cc_footphase / scale);
quickqueue();
keyhandler = [] (int sym, int uni) {
@ -1104,7 +1114,7 @@ void showCustomizeChar() {
if(xuni == 'a') { shmup::cpid_edit++; shmup::cpid_edit %= 60; }
if(xuni == 'g') {
cs.charid++;
if(cs.charid == 2 && !princess::everSaved) cs.charid = 4;
if(cs.charid == 2 && !princess::everSaved && !autocheat) cs.charid = 4;
cs.charid %= 10;
}
if(xuni == 'p') vid.samegender = !vid.samegender;
@ -1148,3 +1158,62 @@ void resetConfigMenu() {
};
}
void selectLanguageScreen() {
gamescreen(4);
dialog::init("select language"); // intentionally not translated
int v = vid.language;
dynamicval<int> d(vid.language, -1);
for(int i=0; i<NUMLAN-1 || i == v; i++) {
vid.language = i;
dialog::addSelItem(XLAT("EN"), its(100 * transcompleteness[i] / transcompleteness[0]) + "%", 'a'+i);
}
dialog::addBreak(50);
vid.language = -1;
dialog::addBoolItem(XLAT("default") + ": " + XLAT("EN"), v == -1, '0');
dialog::addItem(XLAT("exit configuration"), '1');
dialog::addBreak(50);
vid.language = v;
if(lang() >= 1)
dialog::addHelp(XLAT("add credits for your translation here"));
else
dialog::addHelp(XLAT("original language"));
if(lang() != 0) {
string tw = "";
string s = XLAT("TRANSLATIONWARNING");
if(s != "" && s != "TRANSLATIONWARNING") tw += s;
s = XLAT("TRANSLATIONWARNING2");
if(s != "" && s != "TRANSLATIONWARNING2") { if(tw != "") tw += " "; tw += s; }
if(tw != "") {
dialog::addHelp(tw);
dialog::lastItem().color = 0xFF0000;
}
}
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
char xuni = uni | 96;
if(uni == '0') {
vid.language = -1;
ANDROID_SETTINGS;
}
else if(xuni >= 'a' && xuni < 'a'+NUMLAN) {
vid.language = xuni - 'a';
ANDROID_SETTINGS;
}
else if(doexiton(sym, uni))
popScreen();
};
}

View File

@ -606,40 +606,45 @@ void mainloopiter() {
bool rollchange = (cmode & sm::OVERVIEW) && getcstat >= 2000 && cheater;
if(ev.type == SDL_MOUSEBUTTONDOWN) {
flashMessages();
mousepressed = true;
mousepressed = ev.type == SDL_MOUSEBUTTONDOWN;
if(mousepressed) flashMessages();
mousing = true;
actonrelease = true;
if(ev.button.button==SDL_BUTTON_WHEELDOWN) {
sym = uni = PSEUDOKEY_WHEELDOWN;
bool act = false;
if(vid.quickmouse) {
act = ev.type == SDL_MOUSEBUTTONDOWN;
}
if(ev.button.button==SDL_BUTTON_WHEELUP) {
sym = uni = PSEUDOKEY_WHEELUP;
else {
act = actonrelease && ev.type == SDL_MOUSEBUTTONUP;
actonrelease = ev.type == SDL_MOUSEBUTTONDOWN;
}
else if(ev.button.button == SDL_BUTTON_RIGHT) {
sym = 1; didsomething = true;
}
else if(ev.button.button == SDL_BUTTON_MIDDLE) {
sym = 2; didsomething = true;
}
}
if(!act) ;
if(ev.type == SDL_MOUSEBUTTONUP) {
mousepressed = false;
mousing = true;
if(ev.button.button==SDL_BUTTON_RIGHT || leftclick)
else if(ev.button.button==SDL_BUTTON_RIGHT || leftclick)
sym = SDLK_F1;
else if(ev.button.button==SDL_BUTTON_MIDDLE || rightclick)
sym = 1, didsomething = true;
else if(ev.button.button == SDL_BUTTON_LEFT && actonrelease) {
else if(ev.button.button == SDL_BUTTON_LEFT) {
sym = getcstat, uni = getcstat, shiftmul = getcshift;
}
else if(ev.button.button == SDL_BUTTON_WHEELUP && rollchange) {
sym = getcstat, uni = getcstat, shiftmul = getcshift, wheelclick = true;
else if(ev.button.button==SDL_BUTTON_WHEELDOWN) {
if(rollchange) {
sym = getcstat, uni = getcstat, shiftmul = getcshift, wheelclick = true;
}
else {
sym = uni = PSEUDOKEY_WHEELDOWN;
}
}
else if(ev.button.button == SDL_BUTTON_WHEELDOWN && rollchange) {
sym = getcstat, uni = getcstat, shiftmul = -getcshift, wheelclick = true;
if(ev.button.button==SDL_BUTTON_WHEELUP) {
if(rollchange) {
sym = getcstat, uni = getcstat, shiftmul = -getcshift, wheelclick = true;
}
else {
sym = uni = PSEUDOKEY_WHEELUP;
}
}
}

394
debug.cpp Normal file
View File

@ -0,0 +1,394 @@
static int orbid = 0;
void debugScreen();
eItem nextOrb() {
orbid++;
eItem i = eItem(orbid % ittypes);
if(itemclass(i) == IC_ORB) return i;
else return nextOrb();
}
eItem randomTreasure() {
eItem i = eItem(hrand(ittypes));
if(itemclass(i) == IC_TREASURE) return i;
else return randomTreasure();
}
eItem randomTreasure2(int cv) {
int bq = 60000, cq = 0;
eItem best = itDiamond;
eItem lt = localTreasureType();
for(int a=1; a<ittypes; a++) {
eItem i = eItem(a);
if(itemclass(i) != IC_TREASURE) continue;
int q = 2*items[i];
if(a == lt) q -= (2*cv-1);
if(a == itEmerald && bearsCamelot(cwt.c->land)) q -= 8;
if(a == itElixir && isCrossroads(cwt.c->land)) q -= 7;
if(a == itIvory && isCrossroads(cwt.c->land)) q -= 6;
if(a == itPalace && isCrossroads(cwt.c->land)) q -= 5;
if(a == itIvory && cwt.c->land == laJungle) q -= 5;
if(a == itIvory && cwt.c->land == laPalace) q -= 5;
if(q < bq) bq = q, cq = 0;
if(q == bq) { cq++; if(hrand(cq) == 0) best = i; }
}
return best;
}
bool isTechnicalLand(eLand l) {
return l == laNone || l == laOceanWall || l == laBarrier || l == laCanvas ||
l == laHauntedWall || l == laHauntedBorder || l == laCA ||
l == laMirrorWall || l == laMirrored || l == laMirrored2;
}
eLand cheatdest;
void cheatMoveTo(eLand l) {
cheatdest = l;
if(l == laCrossroads5) l = laCrossroads;
activateSafety(l);
cheatdest = laNone;
}
bool applyCheat(char u, cell *c = NULL) {
if(u == 'L') {
do {
if(firstland == eLand(landtypes-1))
firstland = eLand(2);
else
firstland = eLand(firstland+1);
}
while(isTechnicalLand(firstland) || isCyclic(firstland));
specialland = firstland;
cheater++; addMessage(XLAT("You will now start your games in %1", firstland));
return true;
}
if(u == 'C') {
cheater++;
cheatMoveTo(laCrossroads);
addMessage(XLAT("Activated the Hyperstone Quest!"));
for(int t=1; t<ittypes; t++)
if(t != itHyperstone && t != itBounty && itemclass(eItem(t)) == IC_TREASURE) {
items[t] = 10;
}
kills[moYeti] = 200;
kills[moDesertman] = 200;
kills[moRunDog] = 200;
kills[moZombie] = 200;
kills[moMonkey] = 200;
kills[moCultist] = 200;
kills[moTroll] = 200;
return true;
}
if(u == 'M') {
for(int i=0; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_ORB)
items[i] = 0;
cheater++; addMessage(XLAT("Orb power depleted!"));
return true;
}
if(u == 'O') {
cheater++; addMessage(XLAT("Orbs summoned!"));
for(int i=0; i<cwt.c->type; i++)
if(passable(cwt.c->mov[i], NULL, 0)) {
eItem it = nextOrb();
cwt.c->mov[i]->item = it;
}
return true;
}
if(u == 'F') {
if(hardcore && !canmove) {
canmove = true;
addMessage(XLAT("Revived!"));
}
else {
items[itOrbFlash] += 1;
items[itOrbTeleport] += 1;
items[itOrbLightning] += 1;
items[itOrbSpeed] += 1;
items[itOrbShield] += 1;
kills[moPlayer] = 0;
cheater++; addMessage(XLAT("Orb power gained!"));
canmove = true;
}
return true;
}
if(u == 'D') {
items[itGreenStone] += 10;
cheater++; addMessage(XLAT("Dead orbs gained!"));
return true;
}
if(u == 'R'-64) buildRosemap();
#if CAP_EDIT
if(u == 'A') {
lastexplore = turncount;
pushScreen(mapeditor::showMapEditor);
return true;
}
if(u == 'A'-64) {
mapeditor::drawcell = mouseover ? mouseover : cwt.c;
pushScreen(mapeditor::showDrawEditor);
return true;
}
#endif
if(u == 'T') {
items[randomTreasure2(10)] += 10;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'T'-64) {
items[randomTreasure2(100)] += 100;
cheater++; addMessage(XLAT("Lots of treasure gained!"));
return true;
}
if(u == 'I'-64) {
items[randomTreasure2(10)] += 25;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'U'-64) {
items[randomTreasure2(10)] += 50;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'Z') {
flipplayer = false;
mirror::act(1, mirror::SPINSINGLE);
cwspin(cwt, 1);
return true;
}
if(u == 'J') {
if(items[localTreasureType()] > 0)
items[localTreasureType()] = 0;
else for(int i=1; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE)
items[i] = 0;
cheater++; addMessage(XLAT("Treasure lost!"));
return true;
}
if(u == 'K') {
for(int i=0; i<motypes; i++) kills[i] += 10;
kills[moPlayer] = 0;
cheater++; addMessage(XLAT("Kills gained!"));
return true;
}
if(u == 'Y') {
for(auto& y: yendor::yi) {
if(y.path[YDIST-1]->item == itKey)
y.path[YDIST-1]->item = itNone;
if(!y.found) items[itKey]++;
y.found = true;
}
cheater++; addMessage(XLAT("Collected the keys!"));
}
if(u == 'P') {
items[itSavedPrincess]++;
princess::saved = true;
princess::everSaved = true;
if(inv::on && !princess::reviveAt)
princess::reviveAt = gold(NO_LOVE);
cheater++; addMessage(XLAT("Saved the Princess!"));
}
if(u == 'S') {
canmove = true;
cheatMoveTo(cwt.c->land);
items[itOrbSafety] += 3;
cheater++; addMessage(XLAT("Activated Orb of Safety!"));
return true;
}
if(u == 'U') {
canmove = true;
cheatMoveTo(firstland);
cheater++; addMessage(XLAT("Teleported to %1!", firstland));
return true;
}
if(u == 'W'-64) {
pushScreen(linepatterns::showMenu);
return true;
}
if(u == 'G'-64) {
timerghost = !timerghost;
cheater++;
addMessage(XLAT("turn count = %1 last exploration = %2 ghost timer = %3",
its(turncount), its(lastexplore), ONOFF(timerghost)));
return true;
}
if(u == 'L'-64) {
cell *c = mouseover;
describeCell(c);
printf("Neighbors:"); for(int i=0; i<c->type; i++) printf("%p ", c->mov[i]);
printf("Barrier: dir=%d left=%d right=%d\n",
c->bardir, c->barleft, c->barright);
return true;
}
if(u == 'C'-64) {
cblind = !cblind;
return true;
}
if(u == 'G') {
pushScreen(debugScreen);
return true;
}
if(u == 'P'-64)
peace::on = !peace::on;
#ifdef CHEAT_DISABLE_ALLOWED
if(u == 'D'-64) {
cheater = 0; autocheat = 0;
return true;
}
#endif
return false;
}
template<class T> string dnameof2(T x) {
string s = dnameof(x);
return s + " (" + its(x) + ")";
}
template<class T> string dnameof2(T x, int p) {
string s = dnameof(x);
return s + " (" + its(x) + "/" + its(p) + ")";
}
vector<pair<cellwalker,int> > drawbugs;
bool debugmode = false;
void debugScreen() {
cmode = vid.xres > vid.yres * 1.4 ? sm::SIDE : 0;
gamescreen(0);
dialog::init(XLAT("debug"));
for(auto& p: drawbugs)
drawBug(p.first, p.second);
if(mouseover) {
drawBug(cellwalker(mouseover, 0), 0x80808080);
char buf[200];
sprintf(buf, "%p", mouseover);
dialog::addSelItem("pointer", buf, 0);
dialog::addSelItem("mpdist", its(mouseover->mpdist), 0);
dialog::addSelItem("land", dnameof2(mouseover->land), 0);
dialog::addSelItem("land param (int)", its(mouseover->landparam), 0);
dialog::addSelItem("land param (hex)", itsh8(mouseover->landparam), 0);
dialog::addSelItem("land param (heat)", fts(HEAT(mouseover)), 0);
dialog::addSelItem("land flags", its(mouseover->landflags)+"/"+itsh2(mouseover->landflags), 0);
dialog::addSelItem("barrier dir", its(mouseover->bardir), 0);
dialog::addSelItem("barrier left", dnameof2(mouseover->barleft), 0);
dialog::addSelItem("barrier right", dnameof2(mouseover->barright), 0);
dialog::addBreak(50);
dialog::addSelItem("wall", dnameof2(mouseover->wall, mouseover->wparam), 0);
dialog::addSelItem("item", dnameof(mouseover->item), 0);
dialog::addBreak(50);
dialog::addSelItem("cpdist", its(mouseover->cpdist), 0);
dialog::addSelItem("pathdist", its(mouseover->pathdist), 0);
dialog::addSelItem("temporary", its(mouseover->aitmp), 0);
dialog::addBreak(50);
dialog::addSelItem("monster", dnameof2(mouseover->monst, mouseover->mondir), 0);
dialog::addSelItem("stuntime/hitpoints", its(mouseover->stuntime)+"/"+its(mouseover->hitpoints), 0);
}
dialog::display();
keyhandler = [] (int sym, int uni) {
handlePanning(sym, uni);
dialog::handleNavigation(sym, uni);
if(applyCheat(uni, mouseover)) ;
else if(sym == PSEUDOKEY_WHEELUP || sym == PSEUDOKEY_WHEELDOWN) ;
else if(doexiton(sym, uni)) {
popScreen();
if(debugmode) quitmainloop = true;
}
};
}
// -- cheat menu --
void showCheatMenu() {
gamescreen(1);
dialog::init("cheat menu");
dialog::addItem(XLAT("return to the game"), ' ');
dialog::addBreak(50);
dialog::addItem(XLAT("gain orb powers"), 'F');
dialog::addItem(XLAT("summon treasure"), 'T');
dialog::addItem(XLAT("summon dead orbs"), 'D');
dialog::addItem(XLAT("lose all treasure"), 'J');
dialog::addItem(XLAT("gain kills"), 'K');
dialog::addItem(XLAT("Hyperstone Quest"), 'C');
dialog::addItem(XLAT("summon orbs"), 'O');
dialog::addItem(XLAT("gain Orb of Yendor"), 'Y');
dialog::addItem(XLAT("summon lots of treasure"), 'T'-64);
dialog::addItem(XLAT("Safety (quick save)"), 'S');
dialog::addItem(XLAT("Select the land ---"), 'L');
dialog::addItem(XLAT("--- and teleport there"), 'U');
dialog::addItem(XLAT("rotate the character"), 'Z');
dialog::addItem(XLAT("deplete orb powers"), 'M');
dialog::addItem(XLAT("save a Princess"), 'P');
dialog::addItem(XLAT("unlock Orbs of Yendor"), 'Y');
dialog::addItem(XLAT("switch ghost timer"), 'G'-64);
dialog::addItem(XLAT("switch web display"), 'W'-64);
dialog::addItem(XLAT("peaceful mode"), 'P'-64);
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni != 0) {
applyCheat(uni);
if(uni == 'F' || uni == 'C' || uni == 'O' ||
uni == 'S' || uni == 'U' || uni == 'G' ||
uni == 'W' || uni == 'I' || uni == 'E' ||
uni == 'H' || uni == 'B' || uni == 'M' ||
uni == 'M' || uni == 'Y'-64 || uni == 'G'-64 ||
uni == ' ' || uni == 8 || uni == 13 ||
uni == SDLK_ESCAPE || uni == 'q' || uni == 'v' || sym == SDLK_ESCAPE ||
sym == SDLK_F10)
popScreen();
}
};
}
#ifdef BACKTRACE
#include <execinfo.h>
#endif
void modalDebug(cell *c) {
viewctr.h = c->master;
pushScreen(debugScreen);
debugmode = true;
mainloop();
debugmode = false;
quitmainloop = false;
}
void raiseBuggyGeneration(cell *c, const char *s) {
printf("procgen error (%p): %s\n", c, s);
if(!errorReported) {
addMessage(string("something strange happened in: ") + s);
errorReported = true;
}
#ifdef BACKTRACE
void *array[1000];
size_t size;
// get void*'s for all entries on the stack
size = backtrace(array, 1000);
// print out all the frames to stderr
backtrace_symbols_fd(array, size, STDERR_FILENO);
#endif
// return;
if(cheater) {
drawbugs.emplace_back(cellwalker(c,0), 0xFF000080);
modalDebug(c);
drawbugs.pop_back();
}
else
c->item = itBuggy;
}

View File

@ -147,6 +147,19 @@ namespace dialog {
items.push_back(it);
}
void addBigItem(string body, int key) {
item it;
it.type = diBigItem;
it.body = body;
it.keycaption = keyname(key);
it.key = key;
it.color = 0xC06000;
it.colors = 0xFFD500;
it.colorc = 0xFF8000;
it.scale = 150;
items.push_back(it);
}
int addBreak(int val) {
item it;
it.type = diBreak;
@ -223,7 +236,7 @@ namespace dialog {
tothei += dfspace * items[i].scale / 100;
if(items[i].type == diItem)
innerwidth = max(innerwidth, textwidth(dfsize * items[i].scale / 100, items[i].body));
if(items[i].type == diTitle || items[i].type == diInfo)
if(items[i].type == diTitle || items[i].type == diInfo || items[i].type == diBigItem)
dialogwidth = max(dialogwidth, textwidth(dfsize * items[i].scale / 100, items[i].body) * 10/9);
}
}
@ -287,7 +300,7 @@ namespace dialog {
if(I.type == diTitle || I.type == diInfo) {
displayfr(dcenter, mid, 2, dfsize * I.scale/100, I.body, I.color, 8);
}
else if(I.type == diItem) {
else if(I.type == diItem || I.type == diBigItem) {
bool xthis = (mousey >= top && mousey < tothei);
#if ISMOBILE
if(xthis && mousepressed)
@ -301,10 +314,15 @@ namespace dialog {
I.color = (xthis&&mousepressed&&actonrelease) ? I.colorc : I.colors;
}
#endif
if(!mousing)
displayfr(keyx, mid, 2, dfsize * I.scale/100, I.keycaption, I.colork, 16);
displayfr(itemx, mid, 2, dfsize * I.scale/100, I.body, I.color, 0);
displayfr(valuex, mid, 2, dfsize * I.scale/100, I.value, I.colorv, 0);
if(I.type == diBigItem) {
displayfr(dcenter, mid, 2, dfsize * I.scale/100, I.body, I.color, 8);
}
else {
if(!mousing)
displayfr(keyx, mid, 2, dfsize * I.scale/100, I.keycaption, I.colork, 16);
displayfr(itemx, mid, 2, dfsize * I.scale/100, I.body, I.color, 0);
displayfr(valuex, mid, 2, dfsize * I.scale/100, I.value, I.colorv, 0);
}
if(xthis) getcstat = I.key;
}
else if(I.type == diSlider) {
@ -322,24 +340,28 @@ namespace dialog {
}
}
}
bool isitem(item& it) {
return it.type == diItem || it.type == diBigItem;
}
void handleNavigation(int &sym, int &uni) {
#if !ISMOBILE
if(uni == '\n' || uni == '\r' || sym == SDLK_KP5)
for(int i=0; i<size(items); i++)
if(items[i].type == diItem)
if(isitem(items[i]))
if(items[i].body == highlight_text) {
uni = sym = items[i].key;
return;
}
if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) {
for(int i=0; i<size(items); i++)
if(items[i].type == diItem)
if(isitem(items[i]))
highlight_text = items[i].body;
}
if(sym == SDLK_PAGEUP || sym == SDLK_KP9) {
for(int i=0; i<size(items); i++)
if(items[i].type == diItem) {
if(isitem(items[i])) {
highlight_text = items[i].body;
break;
}
@ -347,11 +369,11 @@ namespace dialog {
if(sym == SDLK_UP || sym == SDLK_KP8) {
string last = "";
for(int i=0; i<size(items); i++)
if(items[i].type == diItem)
if(isitem(items[i]))
last = items[i].body;
uni = sym = 0;
for(int i=0; i<size(items); i++)
if(items[i].type == diItem) {
if(isitem(items[i])) {
if(items[i].body == highlight_text) {
highlight_text = last; return;
}
@ -362,12 +384,12 @@ namespace dialog {
if(sym == SDLK_DOWN || sym == SDLK_KP2) {
int state = 0;
for(int i=0; i<size(items); i++)
if(items[i].type == diItem) {
if(isitem(items[i])) {
if(state) { highlight_text = items[i].body; return; }
else if(items[i].body == highlight_text) state = 1;
}
for(int i=0; i<size(items); i++)
if(items[i].type == diItem)
if(isitem(items[i]))
highlight_text = items[i].body;
uni = sym = 0;
}

View File

@ -6,6 +6,10 @@
const char *scorefile = "fakemobile_score.txt";
const char *conffile = "fakemobile_config.txt";
#include <string>
std::string levelfile = "fakemobile_level.txt";
std::string picfile = "fakemobile_pic.txt";
#include <SDL/SDL.h>
#include "init.cpp"

View File

@ -3601,6 +3601,35 @@ void explodeAround(cell *c) {
}
}
void killHardcorePlayer(int id, flagtype flags) {
charstyle& cs = getcs(id);
cell *c = playerpos(id);
if(flags & AF_FALL)
fallingMonsterAnimation(c, moPlayer);
else for(int i=0; i<6; i++) {
drawParticle(c, cs.skincolor >> 8, 100);
drawParticle(c, cs.haircolor >> 8, 125);
if(cs.charid)
drawParticle(c, cs.dresscolor >> 8, 150);
else
drawParticle(c, cs.skincolor >> 8, 150);
if(cs.charid == 3)
drawParticle(c, cs.dresscolor2 >> 8, 175);
else
drawParticle(c, cs.skincolor >> 8, 150);
drawParticle(c, cs.swordcolor >> 8, 200);
}
if(multi::players > 1 && multi::activePlayers() > 1) {
multi::leaveGame(id);
}
else {
canmove = false;
achievement_final(true);
msgscroll = 0;
}
}
void killThePlayer(eMonster m, int id, flagtype flags) {
if(markOrb(itOrbShield)) return;
if(shmup::on) {
@ -3619,13 +3648,7 @@ void killThePlayer(eMonster m, int id, flagtype flags) {
}
else if(hardcore) {
addMessage(XLAT("You are killed by %the1!", m));
if(multi::players > 1 && multi::activePlayers() > 1)
multi::leaveGame(id);
else {
canmove = false;
achievement_final(true);
msgscroll = 0;
}
killHardcorePlayer(id, flags);
}
else if(m == moLightningBolt && lastmovetype == lmAttack && isAlchAny(playerpos(id))) {
addMessage(XLAT("You are killed by %the1!", m));
@ -5196,6 +5219,7 @@ void movemonsters() {
bool checkNeedMove(bool checkonly, bool attacking) {
if(items[itOrbDomination] > ORBBASE && cwt.c->monst)
return false;
int flags = 0;
if(cwt.c->monst) {
if(checkonly) return true;
if(isMountable(cwt.c->monst))
@ -5212,6 +5236,7 @@ bool checkNeedMove(bool checkonly, bool attacking) {
if(markOrb2(itOrbAether)) return false;
if(markOrb2(itOrbFish)) return false;
if(checkonly) return true;
flags |= AF_FALL;
addMessage(XLAT("Ice below you is melting! RUN!"));
}
else if(!attacking && cellEdgeUnstable(cwt.c)) {
@ -5238,6 +5263,7 @@ bool checkNeedMove(bool checkonly, bool attacking) {
else if(cwt.c->wall == waChasm) {
if(markOrb2(itOrbAether)) return false;
if(checkonly) return true;
flags |= AF_FALL;
addMessage(XLAT("The floor has collapsed! RUN!"));
}
else if(items[itOrbAether] > ORBBASE && !passable(cwt.c, NULL, P_ISPLAYER | P_NOAETHER)) {
@ -5251,12 +5277,8 @@ bool checkNeedMove(bool checkonly, bool attacking) {
addMessage(XLAT("Your Aether power has expired! RUN!"));
}
else return false;
if(hardcore) {
canmove = false;
achievement_final(true);
msgscroll = 0;
return false;
}
if(hardcore)
killHardcorePlayer(multi::cpid, flags);
return true;
}
@ -5389,7 +5411,7 @@ bool hasSafeOrb(cell *c) {
c->item == itOrbSafety ||
c->item == itOrbShield ||
c->item == itOrbShell ||
c->item == itOrbYendor;
(c->item == itOrbYendor && yendor::state(c) == yendor::ysUnlocked);
}
void checkmove() {
@ -5592,8 +5614,10 @@ void collectMessage(cell *c2, eItem which) {
addMessage(XLAT("This orb is dead..."));
else if(which == itGreenStone)
addMessage(XLAT("Another Dead Orb."));
else if(itemclass(which) != IC_TREASURE)
addMessage(XLAT("You have found %the1!", which));
else if(itemclass(which) != IC_TREASURE) {
if(c2->wall != waBoat)
addMessage(XLAT("You have found %the1!", which));
}
else if(which == itBabyTortoise) {
playSound(c2, playergender() ? "speak-princess" : "speak-prince");
addMessage(XLAT("Aww, poor %1... where is your family?", which));
@ -5639,6 +5663,18 @@ void collectMessage(cell *c2, eItem which) {
else if(which == itPalace && items[itPalace] == U5-1 && !specialmode) {
addMessage(XLAT("The rug depicts a man in a deep dungeon, unable to leave."));
}
else if(which == itFeather && items[itFeather] == 25-1 && !specialmode && inv::on)
addMessage(XLAT("You feel the presence of free saves on the Crossroads."));
else if(which == itHell && items[itHell] == 25-1 && !specialmode && inv::on)
addMessage(XLAT("You feel the Orbs of Yendor nearby..."));
else if(which == itHell && items[itHell] == 50-1 && !specialmode && inv::on)
addMessage(XLAT("You feel the Orbs of Yendor in the Crossroads..."));
else if(which == itHell && items[itHell] == 100-1 && !specialmode && inv::on)
addMessage(XLAT("You feel the Orbs of Yendor everywhere..."));
else if(which == itBone && items[itBone] % 25 == 24 && !specialmode && inv::on)
addMessage(XLAT("You have gained an offensive power!"));
else if(which == itHell && items[itHell] >= 100 && items[itHell] % 25 == 24 && !specialmode && inv::on)
addMessage(XLAT("A small reward for braving the Hell."));
else if(which == itIvory && items[itIvory] == U5-1 && !specialmode) {
addMessage(XLAT("You feel attuned to gravity, ready to face mountains and dungeons."));
}
@ -5844,7 +5880,7 @@ bool collectItem(cell *c2, bool telekinesis) {
addMessage(XLAT("The Orb of Safety from the Land of Eternal Motion might save you."));
#endif
#define IF(x) if(pg < (x) && g2 >= x)
#define IF(x) if(pg < (x) && g2 >= x && !peace::on)
IF(R60/4)
addMessage(XLAT("Collect treasure to access more different lands..."));
@ -6447,7 +6483,7 @@ bool movepcto(int d, int subdir, bool checkonly) {
placeWater(c2, cwt.c);
moveBoat(c2, cwt.c);
c2->mondir = neighborId(c2, cwt.c);
if(cwt.c->item) moveItem(cwt.c, c2, false), boatmove = true;
if(cwt.c->item) moveItem(cwt.c, c2, true), boatmove = true;
goto boatjump;
}

635
graph.cpp
View File

@ -48,10 +48,10 @@ string mouseovers;
int darken = 0;
struct fallanim {
int t_mon, t_floor;
int t_mon, t_floor, pid;
eWall walltype;
eMonster m;
fallanim() { t_floor = 0; t_mon = 0; walltype = waNone; }
fallanim() { t_floor = 0; t_mon = 0; pid = 0; walltype = waNone; }
};
map<cell*, fallanim> fallanims;
@ -551,9 +551,22 @@ bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks,
}
else if(it == itCompass) {
cell *c1 = findcompass(c);
transmatrix V2;
if(euclid) V2 = V * spin(M_PI/2); // todo incorrect
else V2 = V * rspintox(inverse(V) * pirateCoords);
if(c1) {
transmatrix P = shmup::ggmatrix(c1);
hyperpoint P1 = tC0(P);
if(isPlayerOn(c)) {
queuechr(P1, 2*vid.fsize, 'X', 0x10100 * int(128 + 100 * sin(ticks / 150.)));
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)));
addauraspecial(P1, 0x0000FF, 0);
}
V2 = V * rspintox(inverse(V) * P1);
}
else V2 = V;
V2 = V2 * spin(M_PI * sin(ticks/100.) / 30);
queuepoly(V2, shCompass1, 0xFF8080FF);
queuepoly(V2, shCompass2, 0xFFFFFFFF);
@ -1764,7 +1777,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
return drawMonsterTypeDH(m, c, Vs, col, darkhistory, footphase);
}
for(int i=0; i<numplayers(); i++) if(c == playerpos(i) && !shmup::on && mapeditor::drawplayer) {
for(int i=0; i<numplayers(); i++) if(c == playerpos(i) && !shmup::on && mapeditor::drawplayer &&
!(hardcore && !canmove)) {
if(!nospins) {
Vs = playerV;
if(multi::players > 1 ? multi::flipped[i] : flipplayer) Vs = Vs * pispin;
@ -1789,15 +1803,9 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
return false;
}
bool showPirateX;
cell *keycell, *pirateTreasureSeek, *pirateTreasureFound;
hyperpoint pirateCoords;
double downspin;
cell *straightDownSeek;
int keycelldist;
#define AURA 180
int aurac[AURA+1][4];
@ -1806,16 +1814,28 @@ bool haveaura() {
return pmodel == mdDisk && (!sphere || vid.alpha > 10) && !euclid && vid.aurastr>0 && !svg::in && (auraNOGL || vid.usingGL);
}
vector<pair<int, int> > auraspecials;
int auramemo;
void clearaura() {
if(!haveaura()) return;
for(int a=0; a<AURA; a++) for(int b=0; b<4; b++)
aurac[a][b] = 0;
auraspecials.clear();
auramemo = 128 * 128 / vid.aurastr;
}
void addauraspecial(const hyperpoint& h, int col, int dir) {
if(!haveaura()) return;
int r = int(2*AURA + dir + atan2(h[0], h[1]) * AURA / 2 / M_PI) % AURA;
auraspecials.emplace_back(r, col);
}
void addaura(const hyperpoint& h, int col, int fd) {
if(!haveaura()) return;
int r = int(2*AURA + atan2(h[0], h[1]) * AURA / 2 / M_PI) % AURA;
aurac[r][3] += ((128 * 128 / vid.aurastr) << fd);
aurac[r][3] += auramemo << fd;
col = darkened(col);
aurac[r][0] += (col>>16)&255;
aurac[r][1] += (col>>8)&255;
@ -1845,6 +1865,11 @@ void drawaura() {
if(sphere) rad /= sqrt(vid.alphax*vid.alphax - 1);
for(int v=0; v<4; v++) sumaura(v);
for(auto& p: auraspecials) {
int r = p.first;
aurac[r][3] = auramemo;
for(int k=0; k<3; k++) aurac[r][k] = (p.second >> (8*k)) & 255;
}
#if CAP_SDL || CAP_GL
double bak[3];
@ -2242,212 +2267,8 @@ void setcolors(cell *c, int& wcol, int &fcol) {
wcol = fcol = winf[c->wall].color;
// floor colors for all the lands
if(c->land == laKraken) fcol = 0x20A020;
if(c->land == laBurial) fcol = linf[laBurial].color;
if(c->land == laTrollheim) fcol = linf[c->land].color;
if(c->land == laBarrier) fcol = linf[c->land].color;
if(c->land == laOceanWall) fcol = linf[c->land].color;
if(c->land == laAlchemist) {
fcol = 0x202020;
if(c->item && !(conformal::includeHistory && eq(c->aitmp, sval)))
fcol = wcol = iinf[c->item].color;
}
if(c->land == laBull)
fcol = 0x800080;
if(c->land == laCA)
fcol = 0x404040;
if(c->land == laReptile) {
fcol = reptilecolor(c);
}
if(c->land == laCrossroads) fcol = (vid.goteyes2 ? 0xFF3030 : 0xFF0000);
if(c->land == laCrossroads2) fcol = linf[laCrossroads2].color;
if(c->land == laCrossroads3) fcol = linf[laCrossroads3].color;
if(c->land == laCrossroads4) fcol = linf[laCrossroads4].color;
if(c->land == laCrossroads5) fcol = linf[laCrossroads5].color;
if(isElemental(c->land)) fcol = linf[c->land].color;
if(c->land == laDesert) fcol = 0xEDC9AF;
if(c->land == laCaves) fcol = 0x202020;
if(c->land == laEmerald) fcol = 0x202020;
if(c->land == laDeadCaves) fcol = 0x202020;
if(c->land == laJungle) fcol = (vid.goteyes2 ? 0x408040 : 0x008000);
if(c->land == laMountain) {
if(euclid || c->master->alt)
fcol = celldistAlt(c) & 1 ? 0x604020 : 0x302010;
else fcol = 0;
if(c->wall == waPlatform) wcol = 0xF0F0A0;
}
if(c->land == laWineyard) fcol = 0x006000;
if(c->land == laMirror || c->land == laMirrorWall || c->land == laMirrorOld)
fcol = 0x808080;
if(c->land == laMotion) fcol = 0xF0F000;
if(c->land == laGraveyard) fcol = 0x107010;
if(c->land == laDryForest) fcol = gradient(0x008000, 0x800000, 0, c->landparam, 10);
if(c->land == laRlyeh) fcol = (vid.goteyes2 ? 0x4080C0 : 0x004080);
if(c->land == laPower) fcol = linf[c->land].color;
if(c->land == laHell) fcol = (vid.goteyes2 ? 0xC03030 : 0xC00000);
if(c->land == laLivefjord) fcol = 0x306030;
if(c->land == laWildWest) fcol = linf[c->land].color;
if(c->land == laHalloween) fcol = linf[c->land].color;
if(c->land == laMinefield) fcol = 0x80A080;
if(c->land == laCaribbean) fcol = 0x006000;
if(c->land == laRose) fcol = linf[c->land].color;
if(c->land == laCanvas) fcol = c->landparam;
if(c->land == laRedRock) fcol = linf[c->land].color;
if(c->land == laDragon) fcol = linf[c->land].color;
if(c->land == laStorms) fcol = linf[c->land].color;
if(c->land == laPalace) {
fcol = 0x806020;
if(c->wall == waClosedGate || c->wall == waOpenGate)
fcol = wcol;
}
if(c->land == laElementalWall)
fcol = (linf[c->barleft].color>>1) + (linf[c->barright].color>>1);
if(c->land == laZebra) {
fcol = 0xE0E0E0;
if(c->wall == waTrapdoor) fcol = 0x808080;
}
if(c->land == laCaribbean && (c->wall == waCIsland || c->wall == waCIsland2))
fcol = wcol = winf[c->wall].color;
if(isHive(c->land)) {
fcol = linf[c->land].color;
if(c->wall == waWaxWall) wcol = c->landparam;
if(items[itOrbInvis] && c->wall == waNone && c->landparam)
fcol = gradient(fcol, 0xFF0000, 0, c->landparam, 100);
if(c->bardir == NOBARRIERS && c->barleft)
fcol = minf[moBug0+c->barright].color;
}
if(isWarped(c->land)) {
fcol = pseudohept(c) ? 0x80C080 : 0xA06020;
if(c->wall == waSmallTree) wcol = 0x608000;
}
if(c->land == laTortoise) {
fcol = tortoise::getMatchColor(getBits(c));
if(c->wall == waBigTree) wcol = 0x709000;
else if(c->wall == waSmallTree) wcol = 0x905000;
}
if(c->land == laOvergrown || c->land == laClearing) {
fcol = (c->land == laOvergrown/* || (celldistAlt(c)&1)*/) ? 0x00C020 : 0x60E080;
if(c->wall == waSmallTree) wcol = 0x008060;
else if(c->wall == waBigTree) wcol = 0x0080C0;
}
if(c->land == laTemple) {
int d = showoff ? 0 : (euclid||c->master->alt) ? celldistAlt(c) : 99;
if(chaosmode)
fcol = 0x405090;
else if(d % TEMPLE_EACH == 0)
fcol = gradient(0x304080, winf[waColumn].color, 0, 0.5, 1);
// else if(c->type == 7)
// wcol = 0x707070;
else if(d% 2 == -1)
fcol = 0x304080;
else
fcol = 0x405090;
}
if(isHaunted(c->land)) {
int itcolor = 0;
for(int i=0; i<c->type; i++) if(c->mov[i] && c->mov[i]->item)
itcolor = 1;
if(c->item) itcolor |= 2;
fcol = 0x609F60 + 0x202020 * itcolor;
forCellEx(c2, c) if(c2->monst == moFriendlyGhost)
fcol = gradient(fcol, fghostcolor(ticks, c2), 0, .25, 1);
if(c->monst == moFriendlyGhost)
fcol = gradient(fcol, fghostcolor(ticks, c), 0, .5, 1);
if(c->wall == waSmallTree) wcol = 0x004000;
else if(c->wall == waBigTree) wcol = 0x008000;
}
if(c->land == laCamelot) {
int d = showoff ? 0 : ((euclid||c->master->alt) ? celldistAltRelative(c) : 0);
#if CAP_TOUR
if(!tour::on) camelotcheat = false;
if(camelotcheat)
fcol = (d&1) ? 0xC0C0C0 : 0x606060;
else
#endif
if(d < 0) {
fcol = 0xA0A0A0;
}
else {
// a nice floor pattern
int v = emeraldval(c);
int v0 = (v&~3);
bool sw = (v&1);
if(v0 == 8 || v0 == 12 || v0 == 20 || v0 == 40 || v0 == 36 || v0 == 24)
sw = !sw;
if(sw)
fcol = 0xC0C0C0;
else
fcol = 0xA0A0A0;
}
}
if(c->land == laPrairie) {
/* if(isWateryOrBoat(c)) {
if(prairie::isriver(c))
fcol = ((c->LHU.fi.rval & 1) ? 0x000090 : 0x0000E0)
+ int(16 * wavefun(ticks / 200. + (c->wparam)*1.5))
+ ((prairie::next(c) ? 0 : 0xC00000));
else
fcol = 0x000080;
} */
if(prairie::isriver(c)) {
fcol = ((c->LHU.fi.rval & 1) ? 0x402000: 0x503000);
}
else {
fcol = 0x004000 + 0x001000 * c->LHU.fi.walldist;
fcol += 0x10000 * (255 - 511 / (1 + max((int) c->LHU.fi.flowerdist, 1)));
// fcol += 0x1 * (511 / (1 + max((int) c->LHU.fi.walldist2, 1)));
}
}
else if(isIcyLand(c) && isIcyWall(c)) {
float h = HEAT(c);
bool showcoc = c->land == laCocytus && chaosmode && !wmescher;
if(h < -0.4)
wcol = gradient(showcoc ? 0x4080FF : 0x4040FF, 0x0000FF, -0.4, h, -1);
else if(h < 0)
wcol = gradient(showcoc ? 0x80C0FF : 0x8080FF, showcoc ? 0x4080FF : 0x4040FF, 0, h, -0.4);
else if(h < 0.2)
wcol = gradient(showcoc ? 0x80C0FF : 0x8080FF, 0xFFFFFF, 0, h, 0.2);
// else if(h < 0.4)
// wcol = gradient(0xFFFFFF, 0xFFFF00, 0.2, h, 0.4);
else if(h < 0.6)
wcol = gradient(0xFFFFFF, 0xFF0000, 0.2, h, 0.6);
else if(h < 0.8)
wcol = gradient(0xFF0000, 0xFFFF00, 0.6, h, 0.8);
else
wcol = 0xFFFF00;
if(c->wall == waFrozenLake)
fcol = wcol;
else
fcol = (wcol & 0xFEFEFE) >> 1;
if(c->wall == waLake)
fcol = wcol = (wcol & 0xFCFCFC) >> 2;
}
else if(isWateryOrBoat(c) || c->wall == waReptileBridge) {
// water colors
if(isWateryOrBoat(c) || c->wall == waReptileBridge) {
if(c->land == laOcean)
fcol = (c->landparam > 25 && !chaosmode) ? 0x000090 :
0x1010C0 + int(32 * sin(ticks / 500. + (chaosmode ? c->CHAOSPARAM : c->landparam)*1.5));
@ -2474,56 +2295,259 @@ void setcolors(cell *c, int& wcol, int &fcol) {
else
fcol = wcol;
}
else if(c->land == laOcean) {
if(chaosmode)
fcol = gradient(0xD0A090, 0xD0D020, 0, c->CHAOSPARAM, 30);
else
fcol = gradient(0xD0D090, 0xD0D020, -1, sin((double) c->landparam), 1);
}
if(c->land == laEmerald) {
if(c->wall == waCavefloor || c->wall == waCavewall) {
fcol = wcol = gradient(winf[waCavefloor].color, 0xFF00, 0, 0.5, 1);
if(c->wall == waCavewall) wcol = 0xC0FFC0;
// floor colors for all the lands
else switch(c->land) {
case laBurial: case laTrollheim: case laBarrier: case laOceanWall:
case laCrossroads2: case laCrossroads3: case laCrossroads4: case laCrossroads5:
case laRose: case laPower: case laWildWest: case laHalloween: case laRedRock:
case laDragon: case laStorms:
fcol = linf[c->land].color; break;
case laDesert: fcol = 0xEDC9AF; break;
case laKraken: fcol = 0x20A020; break;
case laCA: fcol = 0x404040; break;
case laMotion: fcol = 0xF0F000; break;
case laGraveyard: fcol = 0x107010; break;
case laWineyard: fcol = 0x006000; break;
case laLivefjord: fcol = 0x306030; break;
case laMinefield:
fcol = 0x80A080;
if(c->wall == waMineMine && ((cmode & sm::MAP) || !canmove))
fcol = wcol = 0xFF4040;
break;
case laCaribbean:
if(c->wall != waCIsland && c->wall != waCIsland2)
fcol = 0x006000;
break;
case laAlchemist:
fcol = 0x202020;
if(c->item && !(conformal::includeHistory && eq(c->aitmp, sval)))
fcol = wcol = iinf[c->item].color;
break;
case laReptile:
fcol = reptilecolor(c);
break;
case laCrossroads:
fcol = (vid.goteyes2 ? 0xFF3030 : 0xFF0000);
break;
case laCaves: case laEmerald: case laDeadCaves:
fcol = 0x202020;
if(c->land == laEmerald)
if(c->wall == waCavefloor || c->wall == waCavewall) {
fcol = wcol = gradient(winf[waCavefloor].color, 0xFF00, 0, 0.5, 1);
if(c->wall == waCavewall) wcol = 0xC0FFC0;
}
break;
case laJungle:
fcol = (vid.goteyes2 ? 0x408040 : 0x008000);
break;
case laMirror: case laMirrorWall: case laMirrorOld:
fcol = 0x808080;
break;
case laDryForest:
fcol = gradient(0x008000, 0x800000, 0, c->landparam, 10);
break;
case laMountain:
if(euclid || c->master->alt)
fcol = celldistAlt(c) & 1 ? 0x604020 : 0x302010;
else fcol = 0;
if(c->wall == waPlatform) wcol = 0xF0F0A0;
break;
case laRlyeh:
fcol = (vid.goteyes2 ? 0x4080C0 : 0x004080);
break;
case laHell:
fcol = (vid.goteyes2 ? 0xC03030 : 0xC00000);
break;
case laCanvas:
fcol = c->landparam;
break;
case laPalace:
fcol = 0x806020;
if(c->wall == waClosedGate || c->wall == waOpenGate)
fcol = wcol;
break;
case laElementalWall:
fcol = (linf[c->barleft].color>>1) + (linf[c->barright].color>>1);
break;
case laZebra:
fcol = 0xE0E0E0;
if(c->wall == waTrapdoor) fcol = 0x808080;
break;
case laHive:
fcol = linf[c->land].color;
if(c->wall == waWaxWall) wcol = c->landparam;
if(items[itOrbInvis] && c->wall == waNone && c->landparam)
fcol = gradient(fcol, 0xFF0000, 0, c->landparam, 100);
if(c->bardir == NOBARRIERS && c->barleft)
fcol = minf[moBug0+c->barright].color;
break;
case laTortoise:
fcol = tortoise::getMatchColor(getBits(c));
if(c->wall == waBigTree) wcol = 0x709000;
else if(c->wall == waSmallTree) wcol = 0x905000;
break;
case laOvergrown: case laClearing:
fcol = (c->land == laOvergrown/* || (celldistAlt(c)&1)*/) ? 0x00C020 : 0x60E080;
if(c->wall == waSmallTree) wcol = 0x008060;
else if(c->wall == waBigTree) wcol = 0x0080C0;
break;
case laTemple: {
int d = showoff ? 0 : (euclid||c->master->alt) ? celldistAlt(c) : 99;
if(chaosmode)
fcol = 0x405090;
else if(d % TEMPLE_EACH == 0)
fcol = gradient(0x304080, winf[waColumn].color, 0, 0.5, 1);
// else if(c->type == 7)
// wcol = 0x707070;
else if(d% 2 == -1)
fcol = 0x304080;
else
fcol = 0x405090;
break;
}
}
if(c->land == laWhirlwind) {
int wcol[4] = {0x404040, 0x404080, 0x2050A0, 0x5050C0};
fcol = wcol[whirlwind::fzebra3(c)];
}
if(c->land == laIvoryTower)
fcol = 0x10101 * (32 + (c->landparam&1) * 32) - 0x000010;
case laWhirlwind:
if(c->land == laWhirlwind) {
int wcol[4] = {0x404040, 0x404080, 0x2050A0, 0x5050C0};
fcol = wcol[whirlwind::fzebra3(c)];
}
break;
if(c->land == laDungeon) {
int lp = c->landparam % 5;
// xcol = (c->landparam&1) ? 0xD00000 : 0x00D000;
int lps[5] = { 0x402000, 0x302000, 0x202000, 0x282000, 0x382000 };
fcol = lps[lp];
if(c->wall == waClosedGate)
fcol = wcol = 0xC0C0C0;
if(c->wall == waOpenGate)
fcol = wcol = 0x404040;
if(c->wall == waPlatform)
fcol = wcol = 0xDFB520;
}
if(c->land == laEndorian) {
int clev = cwt.c->land == laEndorian ? edgeDepth(cwt.c) : 0;
// xcol = (c->landparam&1) ? 0xD00000 : 0x00D000;
fcol = 0x10101 * (32 + (c->landparam&1) * 32) - 0x000010;
fcol = gradient(fcol, 0x0000D0, clev-10, edgeDepth(c), clev+10);
if(c->wall == waTrunk) fcol = winf[waTrunk].color;
if(c->wall == waCanopy || c->wall == waSolidBranch || c->wall == waWeakBranch) {
fcol = winf[waCanopy].color;
if(c->landparam & 1) fcol = gradient(0, fcol, 0, .75, 1);
case laIvoryTower:
fcol = 0x10101 * (32 + (c->landparam&1) * 32) - 0x000010;
break;
case laDungeon: {
int lp = c->landparam % 5;
// xcol = (c->landparam&1) ? 0xD00000 : 0x00D000;
int lps[5] = { 0x402000, 0x302000, 0x202000, 0x282000, 0x382000 };
fcol = lps[lp];
if(c->wall == waClosedGate)
fcol = wcol = 0xC0C0C0;
if(c->wall == waOpenGate)
fcol = wcol = 0x404040;
if(c->wall == waPlatform)
fcol = wcol = 0xDFB520;
break;
}
}
case laEndorian: {
int clev = cwt.c->land == laEndorian ? edgeDepth(cwt.c) : 0;
// xcol = (c->landparam&1) ? 0xD00000 : 0x00D000;
fcol = 0x10101 * (32 + (c->landparam&1) * 32) - 0x000010;
fcol = gradient(fcol, 0x0000D0, clev-10, edgeDepth(c), clev+10);
if(c->wall == waTrunk) fcol = winf[waTrunk].color;
if(c->wall == waCanopy || c->wall == waSolidBranch || c->wall == waWeakBranch) {
fcol = winf[waCanopy].color;
if(c->landparam & 1) fcol = gradient(0, fcol, 0, .75, 1);
}
break;
}
case laPrairie:
if(prairie::isriver(c)) {
fcol = ((c->LHU.fi.rval & 1) ? 0x402000: 0x503000);
}
else {
fcol = 0x004000 + 0x001000 * c->LHU.fi.walldist;
fcol += 0x10000 * (255 - 511 / (1 + max((int) c->LHU.fi.flowerdist, 1)));
// fcol += 0x1 * (511 / (1 + max((int) c->LHU.fi.walldist2, 1)));
}
break;
case laCamelot: {
int d = showoff ? 0 : ((euclid||c->master->alt) ? celldistAltRelative(c) : 0);
#if CAP_TOUR
if(!tour::on) camelotcheat = false;
if(camelotcheat)
fcol = (d&1) ? 0xC0C0C0 : 0x606060;
else
#endif
if(d < 0) {
fcol = 0xA0A0A0;
}
else {
// a nice floor pattern
int v = emeraldval(c);
int v0 = (v&~3);
bool sw = (v&1);
if(v0 == 8 || v0 == 12 || v0 == 20 || v0 == 40 || v0 == 36 || v0 == 24)
sw = !sw;
if(sw)
fcol = 0xC0C0C0;
else
fcol = 0xA0A0A0;
}
break;
}
case laIce: case laCocytus:
if(isIcyWall(c)) {
float h = HEAT(c);
bool showcoc = c->land == laCocytus && chaosmode && !wmescher;
if(h < -0.4)
wcol = gradient(showcoc ? 0x4080FF : 0x4040FF, 0x0000FF, -0.4, h, -1);
else if(h < 0)
wcol = gradient(showcoc ? 0x80C0FF : 0x8080FF, showcoc ? 0x4080FF : 0x4040FF, 0, h, -0.4);
else if(h < 0.2)
wcol = gradient(showcoc ? 0x80C0FF : 0x8080FF, 0xFFFFFF, 0, h, 0.2);
// else if(h < 0.4)
// wcol = gradient(0xFFFFFF, 0xFFFF00, 0.2, h, 0.4);
else if(h < 0.6)
wcol = gradient(0xFFFFFF, 0xFF0000, 0.2, h, 0.6);
else if(h < 0.8)
wcol = gradient(0xFF0000, 0xFFFF00, 0.6, h, 0.8);
else
wcol = 0xFFFF00;
if(c->wall == waFrozenLake)
fcol = wcol;
else
fcol = (wcol & 0xFEFEFE) >> 1;
if(c->wall == waLake)
fcol = wcol = (wcol & 0xFCFCFC) >> 2;
}
break;
case laOcean:
if(chaosmode)
fcol = gradient(0xD0A090, 0xD0D020, 0, c->CHAOSPARAM, 30);
else
fcol = gradient(0xD0D090, 0xD0D020, -1, sin((double) c->landparam), 1);
break;
default:
if(isElemental(c->land)) fcol = linf[c->land].color;
if(isWarped(c->land)) {
fcol = pseudohept(c) ? 0x80C080 : 0xA06020;
if(c->wall == waSmallTree) wcol = 0x608000;
}
if(isHaunted(c->land)) {
int itcolor = 0;
for(int i=0; i<c->type; i++) if(c->mov[i] && c->mov[i]->item)
itcolor = 1;
if(c->item) itcolor |= 2;
fcol = 0x609F60 + 0x202020 * itcolor;
forCellEx(c2, c) if(c2->monst == moFriendlyGhost)
fcol = gradient(fcol, fghostcolor(ticks, c2), 0, .25, 1);
if(c->monst == moFriendlyGhost)
fcol = gradient(fcol, fghostcolor(ticks, c), 0, .5, 1);
if(c->wall == waSmallTree) wcol = 0x004000;
else if(c->wall == waBigTree) wcol = 0x008000;
}
}
/* if(c->land == laCaribbean && (c->wall == waCIsland || c->wall == waCIsland2))
fcol = wcol = winf[c->wall].color; */
// floors become fcol
if(c->wall == waSulphur || c->wall == waSulphurC || isAlch(c) || c->wall == waPlatform)
fcol = wcol;
@ -2554,9 +2578,6 @@ void setcolors(cell *c, int& wcol, int &fcol) {
if(c->wall == waAncientGrave || c->wall == waFreshGrave || c->wall == waThumperOn || c->wall == waThumperOff || c->wall == waBonfireOff)
fcol = wcol;
if(c->land == laMinefield && c->wall == waMineMine && ((cmode & sm::MAP) || !canmove))
fcol = wcol = 0xFF4040;
if(mightBeMine(c) && mineMarkedSafe(c))
fcol = wcol = gradient(wcol, 0x40FF40, 0, 0.2, 1);
@ -2796,7 +2817,7 @@ void pushdown(cell *c, int& q, const transmatrix &V, double down, bool rezoom, b
bool dodrawcell(cell *c) {
// todo: fix when scrolling
if(!buggyGeneration && c->land != laCanvas && sightrange < 10) {
if(!buggyGeneration && !debugmode && c->land != laCanvas && sightrange < 10) {
// not yet created
if(c->mpdist > 7 && !cheater) return false;
// in the Yendor Challenge, scrolling back is forbidden
@ -3913,6 +3934,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
}
}
if(fa.t_mon) {
dynamicval<int> d(multi::cpid, fa.pid);
int t = (ticks - fa.t_mon);
if(t <= 1500) {
erase = false;
@ -4072,9 +4094,6 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
vid.linewidth /= 3;
}
if(!euclid && (!pirateTreasureSeek || compassDist(c) < compassDist(pirateTreasureSeek)))
pirateTreasureSeek = c;
if(!euclid) {
bool usethis = false;
double spd = 1;
@ -4190,11 +4209,12 @@ void fallingFloorAnimation(cell *c, eWall w, eMonster m) {
fa.walltype = w; fa.m = m;
// drawParticles(c, darkenedby(linf[c->land].color, 1), 4, 50);
}
void fallingMonsterAnimation(cell *c, eMonster m) {
void fallingMonsterAnimation(cell *c, eMonster m, int id) {
if(!mmspatial) return;
fallanim& fa = fallanims[c];
fa.t_mon = ticks;
fa.m = m;
fa.pid = id;
// drawParticles(c, darkenedby(linf[c->land].color, 1), 4, 50);
}
@ -4240,20 +4260,30 @@ void drawMarkers() {
/* for(int i=0; i<12; i++) if(c->type == 5 && c->master == &dodecahedron[i])
queuechr(xc, yc, sc, 4*vid.fsize, 'A'+i, iinf[itOrbDomination].color); */
IG(keycell) {
queuechr(Gm0(keycell), 2*vid.fsize, 'X', 0x10101 * int(128 + 100 * sin(ticks / 150.)));
queuestr(Gm0(keycell), vid.fsize, its(keycelldist), 0x10101 * int(128 - 100 * sin(ticks / 150.)));
}
IG(pirateTreasureFound) {
pirateCoords = Gm0(pirateTreasureFound);
if(showPirateX) {
queuechr(pirateCoords, 2*vid.fsize, 'X', 0x10100 * int(128 + 100 * sin(ticks / 150.)));
if(numplayers() == 1 && cwt.c->master->alt)
queuestr(pirateCoords, vid.fsize, its(-celldistAlt(cwt.c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)));
{
using namespace yendor;
if(yii < size(yi) && !yi[yii].found) {
cell *keycell = NULL;
int i;
for(i=0; i<YDIST; i++)
if(yi[yii].path[i]->cpdist <= sightrange) {
keycell = yi[yii].path[i];
break;
}
if(keycell) {
for(; i<YDIST; i++) {
cell *c = yi[yii].path[i];
if(inscreenrange(c))
keycell = c;
}
hyperpoint H = tC0(shmup::ggmatrix(keycell));
queuechr(H, 2*vid.fsize, 'X', 0x10101 * int(128 + 100 * sin(ticks / 150.)));
queuestr(H, vid.fsize, its(celldistance(cwt.c, yi[yii].key())), 0x10101 * int(128 - 100 * sin(ticks / 150.)));
addauraspecial(H, iinf[itOrbYendor].color, 0);
}
}
}
if(lmouseover && vid.drawmousecircle && ok && DEFAULTCONTROL && MOBON) {
queuecircleat(lmouseover, .8, darkena(lmouseover->cpdist > 1 ? 0x00FFFF : 0xFF0000, 0, 0xFF));
}
@ -4434,27 +4464,6 @@ void drawthemap() {
minf[g.m].name = g.name;
}
keycell = NULL;
pirateTreasureFound = pirateTreasureSeek;
pirateTreasureSeek = NULL;
straightDownSeek = NULL; downspin = 0;
shmup::mousetarget = NULL;
showPirateX = false;
for(int i=0; i<numplayers(); i++) if(multi::playerActive(i))
if(playerpos(i)->item == itCompass) showPirateX = true;
using namespace yendor;
if(yii < size(yi)) {
if(!yi[yii].found)
for(int i=0; i<YDIST; i++)
if(yi[yii].path[i]->cpdist <= sightrange) {
keycell = yi[yii].path[i];
keycelldist = YDIST - i;
}
}
if(mapeditor::autochoose) mapeditor::ew = mapeditor::ewsearch;
mapeditor::ewsearch.dist = 1e30;
modist = 1e20; mouseover = NULL;
@ -4467,6 +4476,8 @@ void drawthemap() {
multi::ccdist[i] = 1e20; multi::ccat[i] = NULL;
}
straightDownSeek = NULL; downspin = 0;
#if ISMOBILE
mouseovers = XLAT("No info about this...");
#endif
@ -4787,7 +4798,7 @@ void normalscreen() {
cmode = sm::NORMAL | sm::DOTOUR | sm::CENTER;
if(viewdists) cmode |= sm::SIDE;
gamescreen(hiliteclick && mmmon ? 1 : 0); drawStats();
if(nomenukey)
if(nomenukey || ISMOBILE)
;
#if CAP_TOUR
else if(tour::on)
@ -4999,3 +5010,21 @@ void animateReplacement(cell *a, cell *b, int layer) {
animateMovement(a, b, layer);
animateMovement(&c1, a, layer);
}
void drawBug(const cellwalker& cw, int col) {
initquickqueue();
transmatrix V = shmup::ggmatrix(cw.c);
if(cw.spin) V = V * ddspin(cw.c, cw.spin, S42);
queuepoly(V, shBugBody, col);
quickqueue();
}
cell *viewcenter() {
if(euclid) return centerover;
else return viewctr.h->c7;
}
bool inscreenrange(cell *c) {
return celldistance(viewcenter(), c) <= (euclid ? sightrange : purehepta ? 9 : 13);
}

View File

@ -28,11 +28,12 @@ string buildHelpText() {
h += XLAT(" (press ESC for some hints about it).");
h += "\n\n";
h += XLAT(
"You can fight most monsters by moving into their location. "
"The monster could also kill you by moving into your location, but the game "
"automatically cancels all moves which result in that.\n\n"
);
if(!shmup::on && !hardcore)
h += XLAT(
"You can fight most monsters by moving into their location. "
"The monster could also kill you by moving into your location, but the game "
"automatically cancels all moves which result in that.\n\n"
);
if(inv::on)
h += XLAT(
@ -56,10 +57,11 @@ string buildHelpText() {
"numbers displayed to get their meanings.\n"
);
#else
h += XLAT(
"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"
);
if(DEFAULTCONTROL)
h += XLAT(
"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"
);
h += XLAT(
"You can right click any element to get more information about it.\n\n"
);
@ -236,12 +238,12 @@ string generateHelpForItem(eItem it) {
"and everywhere after you collect 100.");
}
if(it == itBone || it == itGreenStone) {
/* if(it == itBone || it == itGreenStone) {
help += XLAT(
"\n\nIn the Orb Strategy Mode, dead orbs are available once you collect "
"10 Necromancer Totems in the Graveyard."
);
}
} */
if(it == itFeather || it == itOrbSafety) {
help += XLAT(

39
hud.cpp
View File

@ -50,14 +50,27 @@ const int glyphs = ittypes + motypes;
int gfirsttime[glyphs], glasttime[glyphs], gcopy[glyphs], ikland[glyphs];
int glyphorder[glyphs];
int glyphphase[glyphs];
int glyph_lastticks;
void updatesort() {
for(int i=0; i<glyphs; i++) {
if(ikmerge(i) && gfirsttime[i] == 0)
int ik = ikmerge(i);
if(ik && gfirsttime[i] == 0)
gfirsttime[i] = ticks;
if(ikmerge(i) != gcopy[i])
gcopy[i] = items[i], glasttime[i] = ticks;
}
if(ik != gcopy[i])
gcopy[i] = ik, glasttime[i] = ticks;
int& gp = glyphphase[i];
if(ticks <= glasttime[i]+500)
gp += (ticks - glyph_lastticks);
else if((gp % 500) && i >= ittypes) {
int a = gp;
gp += (ticks - glyph_lastticks);
if(a/500 != gp/500)
gp = gp/500*500;
}
}
glyph_lastticks = ticks;
}
void preparesort() {
@ -148,33 +161,39 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, int color, int qty
int glsize = buttonsize;
if(glyph == '%' || glyph == 'M' || glyph == 'W') glsize = glsize*4/5;
int d = ticks - glasttime[id];
double zoom = (d <= 250 && d >= 0) ? 1.25 - .001 * d : 1;
glsize = int(glsize * zoom);
if(graphglyph()) {
initquickqueue();
if(id >= ittypes) {
eMonster m = eMonster(id - ittypes);
int bsize = buttonsize * 2/3;
double bsize = buttonsize * 2/3;
if(m == moKrakenH) bsize /= 3;
if(m == moKrakenT || m == moDragonTail) bsize /= 2;
if(m == moSlime) bsize = (2*bsize+1)/3;
transmatrix V = atscreenpos(cx+buttonsize/2, cy, bsize);
transmatrix V = atscreenpos(cx+buttonsize/2, cy, bsize*zoom);
int mcol = color;
mcol -= (color & 0xFCFCFC) >> 2;
drawMonsterType(m, NULL, V, mcol, 0);
drawMonsterType(m, NULL, V, mcol, glyphphase[id]/500.0);
}
else {
eItem it = eItem(id);
int bsize = buttonsize / 2;
double bsize = buttonsize / 2;
if(glyph =='*') bsize *= 2;
if(glyph == '$') bsize = (bsize*5+2)/3;
if(glyph == 'o') bsize = (bsize*3+1)/2;
if(glyph == 't') bsize = bsize*5/2;
if(it == itWarning) bsize *= 2;
if(it == itBombEgg || it == itTrollEgg || it == itDodeca) bsize = bsize*3/2;
transmatrix V = atscreenpos(cx+buttonsize/2, cy, bsize);
int icol = color;
icol -= (color & 0xFCFCFC) >> 2;
int ic = itemclass(it);
drawItemType(it, NULL, V, icol, (ic == IC_ORB || ic == IC_NAI) ? ticks*2 : ((glyph == 't' && qty%5) || it == itOrbYendor) ? ticks/2 : 0, false);
bsize = bsize * zoom;
transmatrix V = atscreenpos(cx+buttonsize/2, cy, bsize);
drawItemType(it, NULL, V, icol, (ic == IC_ORB || ic == IC_NAI) ? ticks*2 : ((glyph == 't' && qty%5) || it == itOrbYendor) ? ticks/2 :
glyphphase[id] * 2, false);
}
quickqueue();
}

View File

@ -117,7 +117,7 @@ int arg::readCommon() {
else if(argis("-load")) { PHASE(3); shift(); mapstream::loadMap(loadlevel); }
#endif
else if(argis("-canvas")) {
firstland = euclidland = laCanvas;
firstland = specialland = laCanvas;
shift();
if(args()[1] == 0) mapeditor::whichCanvas = args()[0];
else mapeditor::canvasback = strtol(args(), NULL, 16);
@ -133,9 +133,11 @@ int arg::readCommon() {
}
else if(argis("-W2")) {
shift(); cheatdest = readland(args()); autocheat = true;
showstartmenu = false;
}
else if(argis("-W")) {
shift(); firstland = euclidland = readland(args());
shift(); firstland = specialland = readland(args());
showstartmenu = false;
}
else if(argis("-I")) {
PHASE(3) cheater++; timerghost = false;
@ -186,9 +188,9 @@ int arg::readCommon() {
else if(argis("-mm")) { PHASEFROM(2); vid.monmode = argi(); }
#define TOGGLE(x, param, act) \
else if(args()[0] == '-' && args()[1] == x && !args()[2]) { if(curphase == 3) {act;} else {PHASE(2); param = !param;} } \
else if(args()[0] == '-' && args()[1] == x && args()[2] == '1') { if(curphase == 3 && !param) {act;} else {PHASE(2); param = true;} } \
else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase == 3 && param) {act;} else {PHASE(2); param = false;} }
else if(args()[0] == '-' && args()[1] == x && !args()[2]) { showstartmenu = false; if(curphase == 3) {act;} else {PHASE(2); param = !param;} } \
else if(args()[0] == '-' && args()[1] == x && args()[2] == '1') { showstartmenu = false; if(curphase == 3 && !param) {act;} else {PHASE(2); param = true;} } \
else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { showstartmenu = false; if(curphase == 3 && param) {act;} else {PHASE(2); param = false;} }
TOGGLE('o', vid.usingGL, switchGL())
TOGGLE('C', chaosmode, restartGame('C'))
@ -198,7 +200,18 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
TOGGLE('S', shmup::on, restartGame('s'))
TOGGLE('H', hardcore, switchHardcore())
TOGGLE('R', randomPatternsMode, restartGame('r'))
TOGGLE('i', inv::on, restartGame('i'))
else if(argis("-peace")) {
peace::otherpuzzles = true;
if(curphase == 3) restartGame('P');
else peace::on = true;
}
else if(argis("-pmem")) {
peace::otherpuzzles = false;
if(curphase == 3) restartGame('P');
else peace::on = true;
}
else if(argis("-geo")) {
if(curphase == 3) {
shift(); targetgeometry = (eGeometry) argi();
@ -413,6 +426,8 @@ int main(int argc, char **argv) {
#endif
initAll();
arg::read(3);
if(showstartmenu)
pushScreen(showStartMenu);
mainloop();
finishAll();
profile_info();

27
hyper.h
View File

@ -158,6 +158,7 @@ void loadcs(FILE *f, charstyle& cs, int vernum);
namespace multi {
extern bool shmupcfg;
extern bool alwaysuse;
void recall();
extern cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER];
extern int players;
@ -345,6 +346,7 @@ struct videopar {
#define AA_LINEWIDTH 16
#define AA_FONT 32
#define AA_MULTI 64
#define AA_MULTI16 128 // not configurable
ld linewidth;
int joyvalue, joyvalue2, joypanthreshold;
@ -361,6 +363,8 @@ struct videopar {
int steamscore;
bool drawmousecircle; // draw the circle around the mouse
bool skipstart; // skip the start menu
int quickmouse; // quick mouse on the map
};
extern videopar vid;
@ -544,7 +548,7 @@ extern int sval;
extern int items[ittypes], hiitems[MODECODES][ittypes], kills[motypes], explore[10], exploreland[10][landtypes], landcount[landtypes];
extern eLand firstland, euclidland;
extern eLand firstland, specialland;
bool pseudohept(cell *c);
bool pureHardcore();
extern int cheater;
@ -797,7 +801,7 @@ extern bool timerghost;
namespace dialog {
enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diSlider};
enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diSlider, diBigItem};
struct item {
tDialogItem type;
@ -907,7 +911,7 @@ void commitAnimations(int layer);
void animateReplacement(cell *a, cell *b, int layer);
void fallingFloorAnimation(cell *c, eWall w = waNone, eMonster m = moNone);
void fallingMonsterAnimation(cell *c, eMonster m);
void fallingMonsterAnimation(cell *c, eMonster m, int id = multi::cpid);
// ranks:
enum PPR {
@ -1288,6 +1292,8 @@ void pushThumper(cell *th, cell *cto);
template<class T> T pick(T x, T y) { return hrand(2) ? x : y; }
template<class T> T pick(T x, T y, T z) { switch(hrand(3)) { case 0: return x; case 1: return y; case 2: return z; } return x; }
template<class T> T pick(T x, T y, T z, T v) { switch(hrand(4)) { case 0: return x; case 1: return y; case 2: return z; case 3: return v; } return x; }
template<class T, class... U> bool among(T x, T y) { return x == y; }
template<class T, class... U> bool among(T x, T y, U... u) { return x==y || among(x,u...); }
eLand getNewSealand(eLand old);
bool createOnSea(eLand old);
@ -1356,7 +1362,7 @@ extern hookset<eLand(eLand)> *hooks_nextland;
extern ld shiftmul;
void initcs(charstyle &cs);
charstyle& getcs();
charstyle& getcs(int id = multi::cpid);
struct msginfo {
int stamp;
@ -1470,7 +1476,7 @@ bool needConfirmation();
extern const char* geometrynames_short[gGUARD];
namespace mirror {
cellwalker reflect(cellwalker cw, bool debug = false);
cellwalker reflect(const cellwalker& cw);
}
bool inmirror(eLand l);
@ -1508,3 +1514,14 @@ int gl_width(int size, const char *s);
#ifdef ISMOBILE
extern int andmode;
#endif
void addaura(const hyperpoint& h, int col, int fd);
void addauraspecial(const hyperpoint& h, int col, int dir);
void drawBug(const cellwalker& cw, int col);
void mainloop();
extern bool showstartmenu;
void selectLanguageScreen();
bool inscreenrange(cell *c);

View File

@ -1,8 +1,8 @@
id ICON "hr-icon.ico"
1 VERSIONINFO
FILEVERSION 10,0,0,3
PRODUCTVERSION 10,0,0,3
FILEVERSION 10,0,0,7
PRODUCTVERSION 10,0,0,7
BEGIN
BLOCK "StringFileInfo"
BEGIN
@ -10,12 +10,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Zeno Rogue"
VALUE "FileDescription", "A roguelike in non-euclidean space"
VALUE "FileVersion", "A10.0b"
VALUE "InternalName", "hyper"
VALUE "FileVersion", "A10.0g"
VALUE "InternalName", "hype"
VALUE "LegalCopyright", "Zeno Rogue"
VALUE "OriginalFilename", "hyper.exe"
VALUE "ProductName", "HyperRogue"
VALUE "ProductVersion", "10.0c"
VALUE "ProductVersion", "10.0g"
END
END

View File

@ -1,6 +1,6 @@
#define VER "10.0e"
#define VERNUM 10005
#define VERNUM_HEX 0xA005
#define VER "10.0g"
#define VERNUM 10007
#define VERNUM_HEX 0xA007
#define GEN_M 0
#define GEN_F 1
@ -93,7 +93,7 @@
#endif
#ifndef CAP_EDIT
#define CAP_EDIT (!ISMOBWEB && !ISMINI)
#define CAP_EDIT (!ISWEB && !ISMINI)
#endif
#ifndef CAP_MODEL
@ -330,6 +330,7 @@ const char *loadlevel = NULL;
bool inv::on;
#endif
#include "system.cpp"
#include "debug.cpp"
#include "geometry.cpp"
#include "polygons.cpp"
#include "mapeditor.cpp"
@ -368,6 +369,7 @@ bool fixseed = false;
int startseed = 0;
void initAll() {
showstartmenu = true;
ca::init();
arg::read(1);
srand(time(NULL));
@ -552,7 +554,13 @@ void handleclick(MOBPAR_FORMAL) {
if(andmode >= 10) andmode -= 10;
if(andmode == 3) pushScreen(showMainMenu), andmode = 0;
if(andmode == 3) {
if(tour::on)
showMissionScreen();
else
pushScreen(showMainMenu);
andmode = 0;
}
}
int touchedAt;

View File

@ -70,15 +70,16 @@ namespace inv {
}
void gainOrbs(eItem it, eItem o) {
auto& nx = next[o == itHyperstone ? o : it];
int qty = items[it];
if(it == itHolyGrail) {
remaining[itOrbIllusion] += qty;
next[it] = {qty+1, qty+1, qty+1};
nx = {qty+1, qty+1, qty+1};
}
else {
bool nextfound = false;
if(qty >= 10) remaining[o]++;
else next[it] = {10,10,10}, nextfound = true;
else nx = {10,10,10}, nextfound = true;
int last = 10;
for(int k=0; k<30 || !nextfound; k++) {
int maxstep = 15 + 5 * k;
@ -94,17 +95,47 @@ namespace inv {
else
xnext = last + 1 + irand(maxstep);
if(xnext > qty && !nextfound)
next[it] = { last+1, xnext, last + maxstep }, nextfound = true;
nx = { last+1, xnext, last + maxstep }, nextfound = true;
if(xnext <= qty) remaining[o]++;
last = xnext;
}
}
}
int nextp2(int i) {
int z = 1;
while(z <= i) z <<= 1;
return z;
}
void gainMirrors(int qtl) {
while(qtl > 0) qtl >>= 1, remaining[itOrbMirror]++;
}
vector<eItem> offensiveOrbs = {
itOrbFlash, itOrbLightning, itOrbPsi, itOrbThorns,
itOrbFreedom, itOrbSword, itOrbSword2,
itOrbHorns, itOrbDragon, itOrbStunning
};
vector<eItem> elementalOrbs = {itOrbFire, itOrbWater, itOrbDigging, itOrbAir};
vector<eItem> demonicOrbs = {itOrbFire, itOrbHorns, itOrbSummon};
bool isIn(eItem o, vector<eItem>& l) {
for(auto it: l) if(it == o) return true;
return false;
}
void gainRandomOrbs(vector<eItem> orblist, eItem which, int each, int reduce) {
const int qoff = size(orblist);
for(int i=1; i<qoff; i++) swap(orblist[i], orblist[irand(1+i)]);
for(int i=0; i<20; i++) {
if((i+1)*each <= items[which] - reduce)
remaining[orblist[i%qoff]]++;
}
}
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;
@ -148,24 +179,18 @@ namespace inv {
}
}
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]]++;
gainRandomOrbs(offensiveOrbs, itBone, 25, 0);
gainRandomOrbs(elementalOrbs, itElemental, 20, 0);
gainRandomOrbs(demonicOrbs, itHell, 20, 100);
if(items[itOrbLove] && !items[itSavedPrincess]) items[itSavedPrincess] = 1;
int& r = remaining[itGreenStone];
if(items[itBone] >= 10) {
if(items[itBone] >= 0) {
for(int i=0; i<ittypes; i++) if(i != itGreenStone) {
r += usedup[i];
if(usedup[i] >= TESTMIRRORED) r -= MIRRORED;
if(usedup[i] >= TESTMIRRORED) r -= (MIRRORED - mirrorqty(eItem(i)));
}
}
@ -214,6 +239,10 @@ namespace inv {
"several quests and lands "
"give you extremely powerful Orbs of the Mirror.\n";
string extraline(eItem it, string s) {
return " "+XLAT1(iinf[it].name) + " ("+s+")";
}
void show() {
gamescreen(2);
@ -245,8 +274,8 @@ namespace inv {
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;
ld px = vid.xcenter + 2*rad*pos.first + rad*pos.second;
ld py = vid.ycenter + pos.second * rad3;
int icol = iinf[o].color;
if(!remaining[i]) icol = gradient(icol, 0, 0, .5, 1);
bool gg = graphglyph();
@ -283,7 +312,6 @@ namespace inv {
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);
}
@ -301,13 +329,43 @@ namespace inv {
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);
string extras = "";
for(int k=0; k<ORBLINES; k++) {
auto oi = orbinfos[k];
if(oi.gchance || oi.orb != which) continue;
eItem it = treasureType(oi.l);
extras += extraline(it, "10");
}
if(which == itOrbMirror) {
extras += extraline(itOrbYendor, its(nextp2(items[itOrbYendor])));
extras += extraline(itHolyGrail, its(nextp2(items[itHolyGrail])));
auto& nx = next[itHyperstone];
extras += extraline(itHyperstone, its(nx.min));
}
if(isIn(which, offensiveOrbs)) extras += extraline(itBone, its(items[itBone]/25*25+25) + "?");
if(isIn(which, elementalOrbs)) extras += extraline(itElemental, its(items[itBone]/20*20+20) + "?");
if(isIn(which, demonicOrbs)) extras += extraline(itHell, its(max(125, items[itHell]/25*25+25)) + "?");
if(extras != "")
displaystr(vid.xres/2, vid.fsize*5, 2, vid.fsize, XLAT("Extras:")+extras, 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(remaining[which] != 1 || usedup[which]) {
string s = XLAT("Number of uses left: %1", its(remaining[which]));
int us = usedup[which];
if(us >= TESTMIRRORED) s += XLAT(" (mirrored)"), us = us - MIRRORED + mirrorqty(which);
if(us) s += XLAT(" (used %1 times)", its(us));
displaystr(vid.xres/2, vid.yres - vid.fsize*6, 2, vid.fsize, s, icol, 8);
}
#if ISMOBILE==0
string hot = XLAT1("Hotkey: "); hot += getcstat;
displaystr(vid.xres/2, vid.fsize*6, 2, vid.fsize, hot, icol, 8);
displaystr(vid.xres/2, vid.yres - vid.fsize*5, 2, vid.fsize, hot, icol, 8);
#endif
eOrbLandRelation olr = getOLR(oi.orb, getPrizeLand());
@ -330,7 +388,7 @@ namespace inv {
if(orbmap.count(uni)) {
eItem orb = orbmap[uni];
if(!remaining[orb]) ;
if(remaining[orb] <= 0) ;
else if(orb == itOrbMirror) {
mirroring = !mirroring;
// an amusing message
@ -341,21 +399,20 @@ namespace inv {
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);
addMessage(XLAT("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.");
addMessage(XLAT("Each orb type can be mirrored only once."));
mirroring = false;
}
else if(remaining[orb]) {
else if(remaining[orb] > 0) {
usedup[itOrbMirror]++;
usedup[orb] += MIRRORED;
usedup[orb] -= mirrorqty(orb);
usedup[itGreenStone]--;
addMessage(XLAT("You mirror %the1.", orb));
mirroring = false;
}
@ -380,7 +437,10 @@ namespace inv {
else if(uni == '1') plain = !plain;
else if(sym == SDLK_F1)
gotoHelp(which ? generateHelpForItem(which) : NODESCYET);
else if(doexiton(sym, uni)) popScreen();
else if(doexiton(sym, uni)) {
if(mirroring) mirroring = false;
popScreen();
}
};
}

View File

@ -37,7 +37,7 @@ bool buildBarrierNowall(cell *c, eLand l2, bool force = false);
bool safety = false;
eLand firstland = laIce, euclidland = laIce;
eLand firstland = laIce, specialland = laIce;
bool timerghost = true;
eLand lastland;
@ -1000,10 +1000,10 @@ bool grailWasFound(cell *c) {
}
int euclidAlt(short x, short y) {
if(euclidland == laTemple || euclidland == laClearing) {
if(specialland == laTemple || specialland == laClearing) {
return max(int(x), x+y);
}
else if(euclidland == laCaribbean || euclidland == laWhirlpool || euclidland == laMountain) {
else if(specialland == laCaribbean || specialland == laWhirlpool || specialland == laMountain) {
return
min(
min(max(int(-x), -x-y) + 3,
@ -1011,7 +1011,7 @@ int euclidAlt(short x, short y) {
max(int(x), int(-y)) + 3
);
}
else if(euclidland == laPrincessQuest)
else if(specialland == laPrincessQuest)
return eudist(x-EPX, y-EPY);
else return eudist(x-20, y-10);
}
@ -1197,42 +1197,6 @@ void describeCell(cell *c) {
printf("\n");
}
#ifdef BACKTRACE
#include <execinfo.h>
#endif
void raiseBuggyGeneration(cell *c, const char *s) {
printf("procgen error (%p): %s\n", c, s);
if(!errorReported) {
addMessage(string("something strange happened in: ") + s);
errorReported = true;
}
// return;
#ifdef DEBUG_LANDGEN
describeCell(c);
for(int i=0; i<c->type; i++) describeCell(c->mov[i]);
buggyGeneration = true; buggycells.push_back(c);
#else
c->item = itBuggy;
#endif
#ifdef BACKTRACE
void *array[1000];
size_t size;
// get void*'s for all entries on the stack
size = backtrace(array, 1000);
// print out all the frames to stderr
backtrace_symbols_fd(array, size, STDERR_FILENO);
#endif
}
void setland(cell *c, eLand l) {
if(c->land != l) {
c->landparam = 0;
@ -1691,7 +1655,7 @@ bool noChaos(eLand l) {
return
isCrossroads(l) || isCyclic(l) || isHaunted(l) ||
l == laCaribbean || isGravityLand(l) || l == laPrincessQuest ||
l == laPrairie;
l == laPrairie || l == laHalloween;
}
eLand getNewSealand(eLand old) {
@ -1819,7 +1783,7 @@ eLand getNewLand(eLand old) {
tab[cnt++] = laLivefjord;
tab[cnt++] = laMinefield;
tab[cnt++] = laPalace;
if(old == laDragon) LIKELY tab[cnt++] = laReptile;
if(old == laDragon && items[itElixir] >= U10) LIKELY tab[cnt++] = laReptile;
if(kills[moVizier]) tab[cnt++] = laEmerald;
if(items[itFeather] >= U10) tab[cnt++] = laZebra;
tab[cnt++] = laWarpCoast;
@ -1961,7 +1925,7 @@ bool notDippingForExtra(eItem i, eItem x) {
eLand euland[65536];
eLand switchable(eLand nearland, eLand farland, eucoord c) {
if(euclidland == laCrossroads4) {
if(specialland == laCrossroads4) {
if(hrand(15) == 0)
return getNewLand(nearland);
return nearland;
@ -1984,7 +1948,7 @@ eLand switchable(eLand nearland, eLand farland, eucoord c) {
eLand getEuclidLand(eucoord c) {
if(euland[c]) return euland[c];
if(c == 0 || c == eucoord(-1) || c == 1)
return euland[c] = euclidland;
return euland[c] = specialland;
if(euland[eucoord(c-2)] && ! euland[eucoord(c-1)]) getEuclidLand(c-1);
if(euland[eucoord(c+2)] && ! euland[eucoord(c+1)]) getEuclidLand(c+1);
if(euland[eucoord(c-1)]) return
@ -2479,6 +2443,8 @@ int coastval(cell *c, eLand base) {
}
else if(base == laMirrored) {
if(!inmirror(c)) return 0;
if(!c->landparam) return UNKNOWN;
return c->landparam & 255;
}
else {
if(c->land == laOceanWall || c->land == laCaribbean || c->land == laWhirlpool ||
@ -2846,10 +2812,30 @@ int getHauntedDepth(cell *c) {
return -100;
}
const int NOCOMPASS = 1000000;
int compassDist(cell *c) {
if(c->master->alt) return celldistAlt(c);
if(isHaunted(c->land) || c->land == laGraveyard) return getHauntedDepth(c);
return 500;
return NOCOMPASS;
}
cell *findcompass(cell *c) {
int d = compassDist(c);
if(d == NOCOMPASS) return NULL;
while(inscreenrange(c)) {
generateAlts(c->master);
forCellEx(c2, c) if(compassDist(c2) < d) {
c = c2;
d = compassDist(c2);
goto nextk;
}
break;
nextk: ;
}
return c;
}
int towerval(cell *c, cellfunction* cf) {
@ -2930,9 +2916,9 @@ bool buildBarrierNowall(cell *c, eLand l2, bool force) {
void setLandQuotient(cell *c) {
int fv = zebra40(c);
if(fv/4 == 4 || fv/4 == 6 || fv/4 == 5 || fv/4 == 10) fv ^= 2;
if(euclidland == laWarpCoast)
if(specialland == laWarpCoast)
if(fv%4==0 || fv%4 == 2) setland(c, laWarpSea);
if(euclidland == laElementalWall)
if(specialland == laElementalWall)
setland(c, eLand(laEFire + (fv%4)));
}
@ -2945,9 +2931,9 @@ bool quickfind(eLand l) {
}
void setLandSphere(cell *c) {
if(euclidland == laWarpCoast)
if(specialland == laWarpCoast)
setland(c, getHemisphere(c, 0) > 0 ? laWarpCoast : laWarpSea);
if(euclidland == laElementalWall) {
if(specialland == laElementalWall) {
int x = getHemisphere(c, 1);
int y = getHemisphere(c, 2);
if(x > 0 && y > 0) setland(c, laEFire);
@ -2965,34 +2951,34 @@ void setLandSphere(cell *c) {
if(c->land == laElementalWall && c->type != 6)
c->wall = getElementalWall(hrand(2) ? c->barleft : c->barright);
}
if(euclidland == laCrossroads || euclidland == laCrossroads2 || euclidland == laCrossroads3) {
if(specialland == laCrossroads || specialland == laCrossroads2 || specialland == laCrossroads3) {
int x = getHemisphere(c, 1);
if(x == 0 || (euclidland == laCrossroads3 && getHemisphere(c, 2) == 0))
if(x == 0 || (specialland == laCrossroads3 && getHemisphere(c, 2) == 0))
setland(c, laBarrier), c->wall = waBarrier;
else setland(c, euclidland);
if(euclidland == laCrossroads3 && c->type != 6 && c->master->fiftyval == 1)
else setland(c, specialland);
if(specialland == laCrossroads3 && c->type != 6 && c->master->fiftyval == 1)
c->wall = waBigTree;
}
}
void setLandEuclid(cell *c) {
setland(c, euclidland);
if(euclidland == laCrossroads) {
setland(c, specialland);
if(specialland == laCrossroads) {
eucoord x, y;
decodeMaster(c->master, x, y);
setland(c, getEuclidLand(y+2*x));
}
if(euclidland == laCrossroads4) {
if(specialland == laCrossroads4) {
eucoord x, y;
decodeMaster(c->master, x, y);
c->land = getEuclidLand(y);
}
if(euclidland == laWhirlpool) {
if(specialland == laWhirlpool) {
c->land = laOcean;
c->landparam = 99;
}
if(euclidland == laPrincessQuest) setland(c, laPalace);
if(euclidland == laOcean) {
if(specialland == laPrincessQuest) setland(c, laPalace);
if(specialland == laOcean) {
eucoord x, y;
decodeMaster(c->master, x, y);
int y0 = y; if(y>50000) y0 -= 65536; y0 += 10;
@ -3001,7 +2987,7 @@ void setLandEuclid(cell *c) {
else if(y0<0) setland(c, laRlyeh);
else c->landparam = y0;
}
if(euclidland == laIvoryTower || euclidland == laDungeon) {
if(specialland == laIvoryTower || specialland == laDungeon) {
eucoord x, y;
decodeMaster(c->master, x, y);
int y0 = y; if(y>50000) y0 -= 65536; y0 = -y0; y0 -= 5;
@ -3012,7 +2998,7 @@ void setLandEuclid(cell *c) {
c->landparam = y0;
}
}
if(euclidland == laElementalWall) {
if(specialland == laElementalWall) {
eucoord x, y;
decodeMaster(c->master, x, y);
int y0 = y; if(y>32768) y0 -= 65536;
@ -3041,7 +3027,7 @@ void setLandEuclid(cell *c) {
setland(c, laElementalWall);
}
}
if(euclidland == laCrossroads3) {
if(specialland == laCrossroads3) {
eucoord x, y;
decodeMaster(c->master, x, y);
int y0 = y; if(y>32768) y0 -= 65536;
@ -3060,7 +3046,7 @@ void setLandEuclid(cell *c) {
c->wall = waBarrier;
}
}
if(euclidland == laWarpCoast) {
if(specialland == laWarpCoast) {
eucoord x, y;
decodeMaster(c->master, x, y);
@ -3516,7 +3502,7 @@ bool is02(int i) { return i == 0 || i == 2; }
// This function generates all lands. Warning: it's very long!
void setdist(cell *c, int d, cell *from) {
if(signed(c->mpdist) <= d) return;
if(c->mpdist > d+1 && d != BARLEV) setdist(c, d+1, from);
c->mpdist = d;
@ -3546,7 +3532,7 @@ void setdist(cell *c, int d, cell *from) {
if(sphere || torus) setLandSphere(c);
else if(euclid) setLandEuclid(c);
if(quotient) { setland(c, euclidland); setLandQuotient(c); }
if(quotient) { setland(c, specialland); setLandQuotient(c); }
// if(chaosmode) setland(c, getCLand(c));
}
@ -4135,7 +4121,7 @@ void setdist(cell *c, int d, cell *from) {
}
if(c->land == laHell) {
if(hrand(1000) < 36 && celldist(c) >= 3) {
if(hrand(1000) < (purehepta ? 16 : 36) && celldist(c) >= 3) {
for(int i=0; i<c->type; i++) {
cell *c2 = createMov(c, i);
setdist(c2, d+1, c);
@ -5586,8 +5572,8 @@ void wandering() {
if(inmirror(c)) continue;
if(smallbounded && !c->item && hrand(5) == 0 && c->land != laHalloween) {
if(passable(c, NULL, 0) || euclidland == laKraken) {
if(!haveOrbPower() && euclidland != laHell) for(int it=0; it<1000 && !c->item; it++)
if(passable(c, NULL, 0) || specialland == laKraken) {
if(!haveOrbPower() && specialland != laHell) for(int it=0; it<1000 && !c->item; it++)
placeLocalOrbs(c);
if(!c->item) c->item = wanderingTreasure(c);
if(c->item == itShard) {

View File

@ -16,13 +16,18 @@ using namespace std;
template<class T> int size(T x) { return x.size(); }
#define NUMLAN 6
#define NUMLAN 7
// language generator
const char *escape(string s, string dft);
template<class T> struct dictionary {
map<string, T> m;
void add(const string& s, const T& val) { m[s] = val; }
void add(const string& s, const T& val) {
if(m.count(s)) add(s + " [repeat]", val);
else m[s] = val;
}
T& operator [] (const string& s) { return m[s]; }
int count(const string& s) { return m.count(s); }
void clear() { m.clear(); }
@ -88,7 +93,14 @@ typedef unsigned hashcode;
hashcode hashval;
bool isrepeat(const string& s) {
return s.find(" [repeat]") != string::npos;
}
hashcode langhash(const string& s) {
if(isrepeat(s)) {
return langhash(s.substr(0, s.size() - 9)) + 1;
}
hashcode r = 0;
for(int i=0; i<size(s); i++) r = hashval * r + s[i];
return r;
@ -133,6 +145,64 @@ void setstats(set<string>& s, const char* bn) {
printf("// %-10s %5d %5d\n", bn, tc, tlen);
}
void langPL() {
#define S(a,b) d[1].add(a,b);
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[1].add(a,n);}
#include "language-pl.cpp"
#undef N
#undef S
}
void langTR() {
#define S(a,b) d[2].add(a,b);
#define N5(a,b,c,d,e) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = e; nouns[2].add(a,n);}
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[2].add(a,n);}
#include "language-tr.cpp"
#undef N
#undef S
}
void langCZ() {
#define S(a,b) d[3].add(a,b);
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[3].add(a,n);}
#include "language-cz.cpp"
#undef N
#undef S
}
void langRU() {
#define S(a,b) d[4].add(a,b);
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[4].add(a,n);}
#include "language-ru.cpp"
#undef N
#undef S
}
void langDE() {
#define S(a,b) d[5].add(a,b);
#define N(a,b,c,d,e) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = e; nouns[5].add(a,n);}
#include "language-de.cpp"
#undef N
#undef S
}
void langPT() {
#define S(a,b) d[6].add(a,b);
#define N(a,b,c,d,e) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.abl = e; nouns[6].add(a,n);}
#include "language-ptbr.cpp"
#undef N
#undef S
}
int completeness[NUMLAN];
int main() {
nothe.insert("R'Lyeh");
@ -146,42 +216,8 @@ int main() {
allchars.insert("");
allchars.insert("δ");
#define S(a,b) d[1].add(a,b);
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[1].add(a,n);}
#include "language-pl.cpp"
#undef N
#undef S
#define S(a,b) d[2].add(a,b);
#define N5(a,b,c,d,e) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = e; nouns[2].add(a,n);}
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[2].add(a,n);}
#include "language-tr.cpp"
#undef N
#undef S
#define S(a,b) d[3].add(a,b);
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[3].add(a,n);}
#include "language-cz.cpp"
#undef N
#undef S
#define S(a,b) d[4].add(a,b);
#define N(a,b,c,d,e,f) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = f; nouns[4].add(a,n);}
#include "language-ru.cpp"
#undef N
#undef S
#define S(a,b) d[5].add(a,b);
#define N(a,b,c,d,e) \
{noun n; n.genus = b; n.nom = c; n.nomp = d; n.acc = e; n.abl = e; nouns[5].add(a,n);}
#include "language-de.cpp"
#undef N
#undef S
langPL(); langCZ(); langRU();
langTR(); langDE(); langPT();
// verify
set<string> s;
@ -189,12 +225,24 @@ int main() {
for(map<string,string>::iterator it = d[i].m.begin(); it != d[i].m.end(); it++)
s.insert(it->first);
printf("// DO NOT EDIT -- this file is generated automatically with langen\n\n");
for(set<string>::iterator x=s.begin(); x != s.end(); x++) {
string mis = "";
for(int i=1; i<NUMLAN; i++) if(d[i].count(*x) == 0)
mis += d[i]["EN"];
if(mis != "")
printf("// #warning Missing [%s]: %s\n", mis.c_str(), escape(*x, "?"));
string mis = "", mis1 = "";
for(int i=1; i<NUMLAN; i++) if(d[i].count(*x) == 0) {
string which = d[i]["EN"];
if(which != "TR" && which != "DE" && which != "PT-BR")
mis += which;
else
mis1 += which;
}
if(mis != "" && !isrepeat(*x))
printf("// #warning Missing [%s/%s]: %s\n", mis.c_str(), mis1.c_str(), escape(*x, "?"));
if(!isrepeat(*x)) {
completeness[0]++;
for(int i=1; i<NUMLAN; i++) if(d[i].count(*x)) completeness[i]++;
}
}
s.clear();
@ -204,11 +252,20 @@ int main() {
s.insert(it->first);
for(set<string>::iterator x=s.begin(); x != s.end(); x++) {
string mis = "";
for(int i=1; i<NUMLAN; i++) if(nouns[i].count(*x) == 0)
mis += d[i]["EN"];
if(mis != "")
printf("// #warning Missing [%s]: %s\n", mis.c_str(), escape(*x, "?"));
string mis = "", mis1 = "";
for(int i=1; i<NUMLAN; i++) if(nouns[i].count(*x) == 0) {
string which = d[i]["EN"];
if(which != "TR" && which != "DE" && which != "PT-BR")
mis += which;
else mis1 += which;
}
if(mis != "" && !isrepeat(*x))
printf("// #warning Missing [%s/%s]: %s\n", mis.c_str(), mis1.c_str(), escape(*x, "?"));
if(!isrepeat(*x)) {
completeness[0]++;
for(int i=1; i<NUMLAN; i++) if(nouns[i].count(*x)) completeness[i]++;
}
}
#ifdef CHECKALL
@ -240,13 +297,16 @@ int main() {
// printf(" \"%s\",", it->c_str());
if(size(*it) >= 2) { javastring += (*it); vchars.push_back(*it); c++; }
}
printf("// DO NOT EDIT -- this file is generated automatically with langen\n");
printf("\n");
printf("#define NUMEXTRA %d\n", c);
printf("const char* natchars[NUMEXTRA] = {");
for(int i=0; i<c; i++) printf("\"%s\",", vchars[i].c_str());
printf("};\n");
printf("//javastring = \"%s\";\n", javastring.c_str());
printf("\nint transcompleteness[NUMLAN] = {");
for(int i=0; i<NUMLAN; i++) printf("%d, ", completeness[i]);
printf("};\n");
for(int i=1; i<NUMLAN; i++)
for(map<string,string>::iterator it = d[i].m.begin(); it != d[i].m.end(); it++)
@ -305,9 +365,11 @@ int main() {
for(map<hashcode,string>::iterator it = ms.begin(); it != ms.end(); it++) {
string s = it->second;
if(isrepeat(s)) printf("#if REPEATED\n");
printf(" {0x%x, { // %s\n", it->first, escape(s, s));
for(int i=1; i<NUMLAN; i++) printf(" %s,\n", escape(d[i][s], s));
printf(" }},\n");
if(isrepeat(s)) printf("#endif\n");
}
printf(" };\n\n");
@ -315,6 +377,7 @@ int main() {
for(map<hashcode,string>::iterator it = mn.begin(); it != mn.end(); it++) {
string s = it->second;
if(isrepeat(s)) printf("#if REPEATED\n");
printf(" {0x%x, %d, { // \"%s\"\n", it->first,
(nothe.count(s) ? 1:0) + (plural.count(s) ? 2:0),
escape(s, s));
@ -328,6 +391,7 @@ int main() {
}
printf(" }},\n");
if(isrepeat(s)) printf("#endif\n");
}
printf(" };\n");

View File

@ -5780,9 +5780,9 @@ S(
"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)")
// 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í"
@ -5872,8 +5872,115 @@ S(
S("puzzles and exploration", "hádanky a zkoumání")
S("Zebra quotient", "kvocient Zebra")
S("cheats", "cheaty")
S("field quotient", "tělesový kvocient")
S("help for keyboard user", "pomoc pro uživatele klávesnice")
S("mark heptagons", "označit sedmiúhelníky")
S("cheats", "cheaty")
S("help for keyboard users", "pomoc pro uživatele klávesnice")
S("Zebra quotient", "kvocient Zebra")
S("field quotient", "tělesový kvocient")
S("mark heptagons", "označit sedmiúhelníky")
S("projection", "projekce")
S("compass size", "velikost kompasu")
S("Collect as many Dodecahedra as you can, then return here!",
"Získej co možná nejvíc Dvanáctistěnů, a potom se vrať sem!")
S("reset all configuration", "vyresetovat konfiguraci")
S("Are you sure?", "Určitě?")
S("yes, and delete the config file", "ano, a vymaž i konfigurační soubor")
S("yes", "ano")
S("cancel", "zrušit")
S("reset the special game modes", "vyresetovat speciální herní módy")
// extra flavor messages for the OSM
S("You feel the presence of free saves on the Crossroads.",
"Cítíš, že na Křižovatce si můžeš zdarma uložit hru.")
S("You feel the Orbs of Yendor nearby...",
"Cítíš blízkost Yendorských Sfér...")
S("You feel the Orbs of Yendor in the Crossroads...",
"Cítíš Yendorské Sféry na Křižovatce...")
S("You feel the Orbs of Yendor everywhere...",
"Cítíš Yendorské Sféry všude...")
S("You have gained an offensive power!",
"Získal jsi útočnou schopnost!")
S("A small reward for braving the Hell.",
"Malá odměna za to, že ses postavil Peklu.")
S(" (mirrored)", " (zrcadlená)")
S(" (used %1 times)", " (použitá %1krát)")
S("Extras:", "Extra:") // extra Orbs gained in OSM
// cheats
S("unlock Orbs of Yendor", "odemkni Yendorské Sféry")
S("Collected the keys!", "Získal jsi klíče!");
S("Saved the Princess!", "Zachránil jsi Princeznu!")
S("save a Princess", "zachraň Princeznu")
// other
S("Note for mobiles", "Poznámka pro mobilní telefony")
S(
"This tutorial is designed for computers, "
"and keys are given for all actions. It will "
"work without a keyboard though, although less "
"comfortably -- just ignore the keys "
"given and select options from MENU.\n\n"
"Select 'next slide' from MENU.",
"Tento tutorial je navržený pro počítače a u všech akcí "
"jsou uvedeny klávesy. Funguje i bez klávesnice, i když "
"ne tak pohodlně -- prostě ignorujte udávané klávesy a "
"vybírejte možnosti z MENU.\n\n"
"Vyber z MENU 'další snímek'.")
S("skip the start menu", "přeskoč menu 'start'")
S("quick mouse", "rychlá myš")
S("This combination is known to be buggy at the moment.", "Tato kombinace možností v současné době nepracuje správně.")
// extra Princess texts
S("\"I do not like butterflies. They are treacherous.\"",
"\"Nesnáším motýly. Jsou zrádní.\"")
S("\"I hate roses.\"", "\"Nenávidím růže.\"")
S("\"In this world there is plenty of space for everyone. We do not need wars.\"",
"\"V tomhle světě je dost místa pro všechny. Nepotřebujeme války.\"")
S("\"Only the stupid hyperbugs do not understand this.\"",
"\"Jenom ti hloupí hyperhmyzáci tomu nerozumějí.\"")
S("\"I have once talked to a Yendorian researcher... he was only interested in infinite trees.\"",
"\"Jednou se mnou mluvil jeden Yendorský výzkumník... zajímal se jenom o nekonečné stromy.\"")
S("\"Infinite trees are boring. I prefer other graphs.\"",
"\"Nekonečné stromy jsou nudné. Mám raději jiné grafy.\"")
// new start menu
S("skip the start menu", "přeskoč menu 'start'")
S("HyperRogue classic", "klasický HyperRogue")
S("explore the world, collect treasures", "zkoumej svět, sbírej poklady")
S("do not get checkmated", "vyhni se šachmatu")
S("use your Orbs in tough situations", "v obtížných situacích používej Sféry")
S("continuous spacetime", "spojitý časoprostor")
S("(most achievements are not available)", "(většina achievementů není k dispozici)")
S("learn about hyperbolic geometry!", "nauč se o hyperbolické geometrii!")
S("more options", "více možností")
S(
"A strange land filled with mirrors. Break magic mirrors and mirage clouds to "
"gain treasures and helpful Mimics.",
"Podivný kraj plný zrcadel. Rozbíjej magická zrcadla a oblaky přeludů, abys získal poklady a užitečné Mimiky."
)

16582
language-data.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4265,7 +4265,7 @@ S("Watch the Minkowski hyperboloid or the hypersian rug mode with the "
"Oglądaj hiperboloidę Minkowskiego albo tryb hiperskiego dywanu przez czerwono-turkusowe okulary 3D.")
S("0 - return", "0 - powrót")
S("return", "powót")
S("return", "powrót")
S("F1 - help", "F1 - pomoc")
// for the conformal polynomial
@ -5780,10 +5780,6 @@ S(
S("puzzles and exploration", "zagadki i zwiedzanie")
S("cheats", "oszustwa")
S("help for keyboard user", "pomoc dla użytkowników klawiatury")
S("mark heptagons", "oznacz siedmiokąty")
S("Collect as many Dodecahedra as you can, then return here!",
"Zbierz jak najwięcej Dwunastościanów i tu wróć!")
@ -5793,6 +5789,97 @@ S("yes, and delete the config file", "tak, i skasuj plik konfiguracyjny")
S("yes", "tak")
S("cancel", "anuluj")
S("reset the special game modes", "zresetuj specjalne tryby gry")
// extra flavor messages for the OSM
S("You feel the presence of free saves on the Crossroads.",
"Wyczuwasz bezpieczeństwo na Skrzyżowaniach.")
S("You feel the Orbs of Yendor nearby...",
"Czujesz w pobliżu Sfery Yendoru...")
S("You feel the Orbs of Yendor in the Crossroads...",
"Wyczuwasz Sfery Yendoru na Skrzyżowaniach...")
S("You feel the Orbs of Yendor everywhere...",
"Wyczuwasz Sfery Yendoru, wszędzie...")
S("You have gained an offensive power!",
"Zdobywasz moc ofensywną!")
S("A small reward for braving the Hell.",
"Drobna nagroda za zmierzenie się z Piekłem.")
S(" (mirrored)", " (odbite)")
S(" (used %1 times)", " (użyte %1 razy)")
S("Extras:", "Dodatkowe:") // extra Orbs gained in OSM
// cheats
S("unlock Orbs of Yendor", "otwórz Sfery Yendoru")
S("Collected the keys!", "Zebrano klucze!");
S("Saved the Princess!", "Uratowano Księżniczkę!")
S("save a Princess", "uratuj Księżniczkę")
// other
S("Note for mobiles", "Notka dla urządzeń mobilnych")
S(
"This tutorial is designed for computers, "
"and keys are given for all actions. It will "
"work without a keyboard though, although less "
"comfortably -- just ignore the keys "
"given and select options from MENU.\n\n"
"Select 'next slide' from MENU.",
"Ten tutorial jest przeznaczony głównie "
"dla komputerów, i klawisze są podane "
"dla wszystkich akcji. Działa jednak bez "
"klawiatury, choć mniej wygodnie -- "
"ignoruj klawisze i wybieraj opcje z MENU.\n\n"
"given and select options from MENU.\n\n"
"Wybierz z MENU 'następny slajd'.")
S("quick mouse", "szybka mysz")
S("This combination is known to be buggy at the moment.", "Ta kombinacja opcji obecnie działa błędnie.")
// extra Princess texts
S("\"I do not like butterflies. They are treacherous.\"",
"\"Nie lubię motyli. Są zdradzieckie.\"")
S("\"I hate roses.\"", "\"Nienawidzę róż.\"")
S("\"In this world there is plenty of space for everyone. We do not need wars.\"",
"\"W tym świecie jest dość miejsca dla każdego. Nie potrzebujemy wojen.\"")
S("\"Only the stupid hyperbugs do not understand this.\"",
"\"Tylko głupie hiperinsekty tego nie rozumieją.\"")
S("\"I have once talked to a Yendorian researcher... he was only interested in infinite trees.\"",
"\"Odwiedził mnie raz badacz Yendoriański... interesowały go tylko nieskończone drzewa.\"")
S("\"Infinite trees are boring. I prefer other graphs.\"",
"\"Nieskończone drzewa są nudne. Wolę inne grafy.\"")
// new start menu
S("skip the start menu", "pomiń menu startowe")
S("HyperRogue classic", "tryb klasyczny HyperRogue")
S("explore the world, collect treasures", "zwiedzaj świat i zbieraj skarby")
S("do not get checkmated", "nie daj się zaszachować")
S("use your Orbs in tough situations", "używaj Sfer w trudnych sytuacjach")
S("continuous spacetime", "ciągła czasoprzestrzeń")
S("(most achievements are not available)", "(większość osiągnięć niedostępna)")
S("learn about hyperbolic geometry!", "dowiedz się więcej o geometrii hiperbolicznej!")
S("more options", "więcej opcji")
S(
"A strange land filled with mirrors. Break magic mirrors and mirage clouds to "
"gain treasures and helpful Mimics.",
"Dziwna kraina pełna luster. Zbijaj magiczne lustra i mirażowe chmury, "
"by zdobywać skarby i przyjazne Mimiki."
)
#undef Orb

5979
language-ptbr.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2189,6 +2189,9 @@ S("configure player 1", "настройки игрока 1")
S("configure player 2", "настройки игрока 2")
S("configure player 3", "настройки игрока 3")
S("configure player 4", "настройки игрока 4")
S("configure player 5", "настройки игрока 5")
S("configure player 6", "настройки игрока 6")
S("configure player 7", "настройки игрока 7")
S("configure panning", "настройки прокрутки")
S("configure joystick axes", "настройка джойстика")
S("continue playing", "продолжить игру")
@ -5590,5 +5593,476 @@ S(
"Нажмите '5', чтобы выйти из режима Руководства."
)
// Orb Strategy mode
S("Orb Strategy mode", "режим стратегии сфер")
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",
"Ты играешь в режим стратегии сфер. Собирай сокровища и получай "
"доступ к силе магических сфер. В этом режиме условия "
"открытия доступа, как правило, выше, а некоторые земли и миссии "
"дадут тебе очень сильные Сферы зеркала.\n")
S("The treasure gives your magical powers!", "Сокровище дало тебе магическую силу!")
S("Press 'i' to access your magical powers.", "Нажми 'i' для доступа к своим магическим силам.")
S("inventory", "твои сферы")
S("mirror what?", "что отразить?")
S("Which orb to use?", "Какую сферу использовать?")
S("Unlocked by: %1 in %2", "Разблокирована: %1 %abl2")
S(" (next at %1)", " (следующий при %1)")
S(" (next at %1 to %2)", " (следующий при %1 в %2)")
S("Number of uses left: %1", "Осталось применений: %1")
S("You mirror %the1.", "Ты отразил %a1.")
S("You need to stand next to a magic mirror or cloud to use %the1.",
"Ты должен стоять рядом с магическим зеркалом или облаком, чтобы использовать %a1.")
S("Each orb type can be mirrored only once.", "Каждый тип сфер может быть отражён только один раз.")
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\nВ режим стратегии сфер Сфера Йендора появляется в Аду, "
"когда ты соберёшь 25 Адских Ромашек, на Перекрёстке и а Океана, когда ты соберёшь 50, "
"и везде, когда ты соберёшь 100."
);
S(
"\n\nIn the Orb Strategy Mode, dead orbs are available once you collect "
"10 Necromancer Totems in the Graveyard.",
"\n\nВ режиме стратегии сфер Мёртвые сферы доступны после сбора "
"десяти Тотемов некроманта на Кладбище.")
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\nВ режиме стратегии сфер Сферу безопасности можно получить, "
"Перья феникса в Земле вечного движения. "
"Также можно найти неограниченные Сферы вечного движения на Перекрёстке "
"и в Океане (когда соберёшь 25 Перьев феникса) и в Прерии."
)
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\nСобери %a1, чтобы получить дополнительную Сферу зеркала. "
"Ты получишь следующую сферу, когда соберёшь 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\nВ режиме стратегии сфер Сфера удачи также заметно "
"увеличивает частоту Великих стен, Перекрёстков IV "
"и под-земель.")
S("\n\nIn the Orb Strategy Mode, each 25 Necromancer's Totems "
"you are given a random offensive Orb.",
"\n\n режиме стратегии сфер каждый 25 Тотемов некроманта "
"дают тебе случайную атакующую сферу.")
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.",
"Используй Сферу зеркала, чтобы получить копии одной из твоих сфер; "
"отражение слабых сфер обычно даёт больше копий. "
"Ты можешь отражать каждый тип сферы лишь один раз, "
"и только когда ты рядом с зеркалом.")
S("Uses to gain: %1", "Получишь применений: %1")
S("already mirrored", "уже была отражена")
N("your orbs", GEN_F, "Твои Сферы", "Твои Сферы", "Твои Сферы", "Твоим Сферами")
S("Click this to see your orbs.", "Нажми, чтобы увидеть твои Сферы.")
// peaceful mode
S("configure keys/joysticks", "настройки клавиш/джойстика")
S("peaceful mode", "мирный режим")
// config changes
S("Press F5 or 'o' to try again!", "Нажми F5 или 'o', чтобы попробовать ещё раз!")
S("aura brightness", "яркость ауры")
S("aura smoothening factor", "сглаживание ауры")
S("graphics configuration", "настройка графики")
S("special display modes", "специальные режимы отображения")
S("openGL mode", "режим OpenGL")
S("anti-aliasing", "anti-aliasing")
S("line width", "широта линии")
S("configure panning and general keys", "настроить панораму и общие клавиши")
S("\n\nHint: use 'm' to toggle cells quickly",
"\n\nПодсказка: используй 'm', чтобы быстро переключать клетки");
// cell pattern names
S("football", "футбол")
S("dark rainbow landscape", "тёмная радуга")
S("field pattern", "узор поля")
S("field pattern C", "узор поля C")
S("field pattern D", "узор поля D")
S("field pattern N", "узор поля N")
S("field pattern S", "узор поля S")
S("four triangles", "четыре треугольника")
S("big triangles: rings", "большие треугольники: кольца")
// missing for the Tutorial
S("tutorial", "руководство")
S("This Orb is not compatible with the Tutorial.", "Эта сфера не совместима с Руководством.")
// local scores
S("turns", "ходы")
S("cells", "клетки")
S("sort", "сортируй")
S("choose", "выбор")
S("play", "играй")
// draw editor
S("autochoose", "автовыбор")
S("c = choose", "c = выбор")
S("b = switch auto", "b = автопереключение")
// 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!",
"Если ты соберёшь слишком много сокровищ в одной земле, она станет "
"весьма опасной. Попробуй другую землю, когда наберёшь достаточно сокровищ здесь!");
S(
"Remember that you can right click almost anything for more information.",
"Помни, что правая кнопка мыши даст информацию практически обо всём.")
S("Want to understand the geometry in HyperRogue? Try the Tutorial!",
"Хочешь понять геометрию в HyperRogue? Воспользуйся Руководством!");
S(
"Collecting 25 treasures in a given land may be dangerous, "
"but allows magical Orbs of this land to appear in other places!",
"Собирать 25 в одной земле довольно опасно, но это позволяет Сферам "
"из этой земли появляться в других местах!")
S(
"Press ESC to view this screen during the game.",
"Нажми ESC, чтобы увидеть этот экран во время игры.")
S("The 'world overview' shows all the lands in HyperRogue.",
"'Обзор мира' покажет все земли в HyperRogue."
)
S("Press 'o' to see all the lands in HyperRogue.",
"Нажми 'o', чтобы увидеть все земли в 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!",
"Хочешь другой тип игры? Хочешь посложнее?\n"
"HyperRogue содержит много специальных режимов, "
"заметно меняющих игру. Попробуй их!")
S(
"Hyperbolic geometry can be shown in many ways.",
"На гиперболическую геометрию можно смотреть с разных сторон.")
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!",
"Не хочешь проигрывать из-за одной ошибки?\n"
"Хочешь научить аккуратно использовать Сферы?\n"
"Попробуй режим стратегии сфер!")
S(
"Do you think you are playing on a ball? "
"This is far from the truth!\n",
"Думаешь, ты играешь на сфере? Как же это далеко от правды!\n")
S(
"Did you know that the path you take during the game "
"is usually very close to a straight line?\n",
"Ты знал, что путь, который ты проходишь за игру, "
"обычно очень близок к прямой линии?")
S("Show me!", "Покажи!")
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",
"Ты на расстоянии %1 клеток от начала пути или "
"от того места, где ты в последний раз использовал Сферу безопасности. "
"Всего таких клеток %2.\n")
S("about ", "примерно ")
S(" (%1 more digits)", " (ещё цифр: %1)")
S("see how it ended", "смотри, как всё закончилось")
// other missing/new things
S("\n\nOrb unlocked: %1", "\n\nОткрыта сфера: %1")
S("Orb unlocked: %1", "Открыта сфера: %1")
S("\n\nSecondary orb: %1", "\n\nДополнительная сфера: %1")
S(" to submerge", " на погружение")
S(" to surface", " на поверхность")
S("%The1 says, \"not this place, it looks even worse...\"",
"%1 сказал, \"не это место, оно выглядит ещё хуже...\"")
S("torus", "тор")
S(" (click to use)", " (нажми, чтобы использовать)")
N("Hall of Mirrors", GEN_O, "Зеркальный зал", "Зеркальные залы", "Зеркальный зал", "в Зеркальном зале")
Orb("the Mirror", "Зеркала")
N("Reflection", GEN_N, "Отражение", "Отражения", "Отражение", "в Отражении")
N("mirror wall", GEN_F, "зеркальная стена", "зеркальные стены", "зеркальную стену", "зеркальной стеной")
S("This would only move you deeper into the trap!",
"Это только уведёт тебя глубже в ловушку!");
S("You swing your sword at the mirror.", "Ты размахиваешь мечом в сторону зеркала.");
N("Mimic", GEN_M, "Мимик", "Мимики", "Мимика", "Мимиком")
N("Narcissist", GEN_M, "Нарциссист", "Нарциссисты", "Нарциссиста", "Нарциссистом")
N("Mirror Spirit", GEN_M, "Зеркальный дух", "Зеркальные духи", "Зеркального духа", "Зеркальным духом")
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.",
"Этот человек любит глядеть на своё отражение в зеркале. "
"Он верит, что он -- один из самых важных в существ этого мира, "
"и ненавидит любого, кто не восхищается им.")
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.",
"Давным-давно могучий воин охранял эти зеркала, чтобы никто их не разбил. "
"Хотя воин давно мёртв, его отражения живы, "
"и они накажут незваных гостей.\n\n"
"Если ты атакуешь Зеркального духа физически, он замедляется, но не погибает -- "
"больше отражений выходит из зеркала. Используй Мимиков, чтобы уничтожать их.")
// S(" (25 in the Orb Strategy mode)", " (25 в режиме стратегии сфер)")
// S(" (50 in the Orb Strategy mode)", " (50 в режиме стратегии сфер)")
// S(" (not in the Orb Strategy mode)", " (не в режиме стратегии сфер)")
/*
"NEW_ACHIEVEMENT_8_19_NAME" "Общая победа"
"NEW_ACHIEVEMENT_8_19_DESC" "В режиме стратегии сфер получить Сферу Йендора, Святой Грааль, Принцессу и 50 Гиперкамней."
added to old achievements:
"(или 25 в режиме стратегии сфер)"
"(или 50 в режиме стратегии сфер)"
"(не в режиме стратегии сфер)"
These apparently have not been yet translated:
"NEW_ACHIEVEMENT_8_4_NAME" "Адепт Йендора"
"NEW_ACHIEVEMENT_8_4_DESC" "Закончи миссию Йендора."
"NEW_ACHIEVEMENT_8_5_NAME" "Мастер ключей"
"NEW_ACHIEVEMENT_8_5_DESC" "Закончи 5 миссий Йендора."
"NEW_ACHIEVEMENT_8_6_NAME" "Гроссмейстер ключей"
"NEW_ACHIEVEMENT_8_6_DESC" "Закончи 15 миссий Йендора."
"NEW_ACHIEVEMENT_8_7_NAME" "Адепт Тактики"
"NEW_ACHIEVEMENT_8_7_DESC" "Получи 1000 очков в режиме тактики."
"NEW_ACHIEVEMENT_8_8_NAME" "Мастер Тактики"
"NEW_ACHIEVEMENT_8_8_DESC" "Получи 5000 очков в режиме тактики."
"NEW_ACHIEVEMENT_8_9_NAME" "Гроссмейстер Тактики"
"NEW_ACHIEVEMENT_8_9_DESC" "Получи 15000 очков в режиме тактики."
"NEW_ACHIEVEMENT_8_10_NAME" "На другой стороне"
"NEW_ACHIEVEMENT_8_10_DESC" "Найди и собери Зелёную траву."
*/
// peaceful texts
S("memory game", "игра 'память'")
S("display hints", "показать подсказки")
S("hyperbolic puzzles", "гиперболические паззлы")
// missing descriptions
S( "A strange land filled with mirrors. "
"Break magic mirrors and enter clouds of mirage to "
"gain treasures and helpful Mimics.",
"Странная земля, наполненная зеркалами. "
"Разбивай магические зеркала и входи в облака миражей, "
"чтобы найти сокровища и дружелюбных Мимиков.")
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.",
"Идеальная зеркальная стена. Невозможно сломать её или "
"пройти через неё, даже для эфирных существ, "
"и всё, что ты в ней видишь -- отражения реального мира. "
"Ты можешь ударить по отражению мечом, "
"но это не убьёт его в реальном мире. "
"Стена идеально отражает Мимиков, молнии и ракеты. ")
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.",
"В мирном режиме ты можешь исследовать мир без битв; "
"здесь также доступно несколько навигационных головоломок. "
"В игре 'память' ты должен собрать как можно больше додекаэдров и "
"вернуться в точку старта -- гиперболическая геометрия делает это "
"крайне сложным! Другие паззлы включают Курганы (выкопай сокровища "
"с помощью магического меча), Галапагосы (найди взрослую черепаху, "
"соответствующую маленькой черепашке), Камелот (найди центр большого "
"гиперболического круга) и Дворец (следуй за мышкой). "
"Остальные места перечислены для изучения."
);
S("puzzles and exploration", "головоломки и изучение")
S("Zebra quotient", "фактор Зебры")
S("field quotient", "фактор поля")
S("mark heptagons", "пометить семиугольники")
S("projection", "проекция")
S("compass size", "размер компаса")
S("Collect as many Dodecahedra as you can, then return here!",
"Собери как можно больше Додекаэдров и вернись сюда!")
S("reset all configuration", "сбросить все настройки")
S("Are you sure?", "Вы уверены?")
S("yes, and delete the config file", "да, и удалить файл с настройками")
S("yes", "да")
S("cancel", "отменить")
S("reset the special game modes", "сбросить специальные режимы")
// extra flavor messages for the OSM
S("You feel the presence of free saves on the Crossroads.",
"Ты чувствуешь, что можешь безопасно сохраниться на перекрёстке.")
S("You feel the Orbs of Yendor nearby...",
"Ты чувствуешь Сферы Йендора поблизости...")
S("You feel the Orbs of Yendor in the Crossroads...",
"Ты чувствуешь Сферы Йендора на перекрёстке...")
S("You feel the Orbs of Yendor everywhere...",
"Ты чувствуешь Сферы Йендора везде...")
S("You have gained an offensive power!",
"Ты получил атакующую силу!")
S("A small reward for braving the Hell.",
"Небольшая награда для прошедших сквозь Ад.")
S(" (mirrored)", " (отражено)")
S(" (used %1 times)", " (использовано %1 раз)")
S("Extras:", "Дополнительно:") // extra Orbs gained in OSM
// cheats
S("unlock Orbs of Yendor", "открыть Сферы Йендора")
S("Collected the keys!", "Ключи собраны!");
S("Saved the Princess!", "Принцесса спасена!")
S("save a Princess", "спасти Принцессу")
// other
S("Note for mobiles", "Замечание для мобильных устройств")
S(
"This tutorial is designed for computers, "
"and keys are given for all actions. It will "
"work without a keyboard though, although less "
"comfortably -- just ignore the keys "
"given and select options from MENU.\n\n"
"Select 'next slide' from MENU.",
"Это руководство сделано для компьютеров, "
"и клавиши требуются для всех "
"действий. Им можно пользоваться и "
"без клавиатуры, хотя и не так удобно -- "
"просто игнорируй их и выбирай действия в МЕНЮ.\n\n"
"Выбери в МЕНЮ 'следующий слайд'.")
S("skip the start menu", "пропустить начальное меню")
S("quick mouse", "быстрая мышь")
S("This combination is known to be buggy at the moment.", "Эта комбинация пока что работает с ошибками.")
// extra Princess texts
S("\"I do not like butterflies. They are treacherous.\"",
"\"Не люблю бабочек. Они предательницы.\"")
S("\"I hate roses.\"", "\"Ненавижу розы.\"")
S("\"In this world there is plenty of space for everyone. We do not need wars.\"",
"\"В этом мире так много места для каждого. Вам не нужны войны.\"")
S("\"Only the stupid hyperbugs do not understand this.\"",
"\"Только глупые гипержуки не понимают этого.\"")
S("\"I have once talked to a Yendorian researcher... he was only interested in infinite trees.\"",
"\"Со мной беседовал Йендорский исследователь... его интересовали лишь бесконечные деревья.\"")
S("\"Infinite trees are boring. I prefer other graphs.\"",
"\"Бесконечные деревья скучные. Предпочитаю другие графы.\"")
// new start menu
S("skip the start menu", "пропустить начальное меню")
S("HyperRogue classic", "классический режим HyperRogue")
S("explore the world, collect treasures", "изучай мир, собирай сокровища")
S("do not get checkmated", "не дай поставить себе мат")
S("use your Orbs in tough situations", "используй Сферы в трудных ситуациях")
S("continuous spacetime", "непрерывное пространство и время")
S("(most achievements are not available)", "(большинство достижений недоступно)")
S("learn about hyperbolic geometry!", "узнай о гиперболической геометрии!")
S("more options", "больше вариантов")
S(
"A strange land filled with mirrors. Break magic mirrors and mirage clouds to "
"gain treasures and helpful Mimics.",
"Странная земля, полная зеркал. Разбивай волшебные зеркала и облака миражей, "
"чтобы найти сокровища и дружелюбных Мимиков."
)
#undef Orb

View File

@ -3,7 +3,7 @@
// #define CHECKTRANS
#define NUMLAN 6
#define NUMLAN 7
struct stringpar {
string v;
@ -243,6 +243,27 @@ void parrep(string& x, string w, stringpar p) {
rep(x, "%den"+w, "the");
}
}
if(l == 6) {
if(N) {
rep(x, "%"+w, N->n[5].nom);
rep(x, "%P"+w, N->n[5].nomp);
rep(x, "%na"+w, choose4(N->n[5].genus, "o", "a", "os", "as") + " " + N->n[5].nom);
rep(x, "%g"+w, choose4(N->n[5].genus, "do", "da", "dos", "das")+ " " + N->n[5].nom);
rep(x, "%d"+w, choose4(N->n[5].genus, "ao", "à", "aos", "às")+ " " + N->n[5].nom);
rep(x, "%l"+w, choose4(N->n[5].genus, "no", "na", "nos", "nas")+ " " + N->n[5].nom);
rep(x, "%abl"+w, choose4(N->n[5].genus, "pelo", "pela", "pelos", "pelas")+ " " + N->n[5].nom);
rep(x, "%seu"+w, choose4(N->n[5].genus, "seu", "sua", "seus", "suas"));
}
else {
rep(x, "%"+w,p.v);
rep(x, "%P"+w, p.v);
rep(x, "%na"+w, p.v);
rep(x, "%g"+w, p.v);
rep(x, "%d"+w, p.v);
rep(x, "%l"+w, p.v);
rep(x, "%abl"+w, p.v);
}
}
#endif
if(true) {
// proper names (R'Lyeh)

View File

@ -21,7 +21,7 @@ namespace mapeditor {
bool side;
cell *c;
} ew, ewsearch;
bool autochoose;
bool autochoose = ISMOBILE;
#if CAP_EDIT
map<int, cell*> modelcell;
@ -613,7 +613,7 @@ namespace mapeditor {
}
void displayFunctionKeys() {
int fs = vid.fsize + 5;
int fs = min(vid.fsize + 5, vid.yres/26);
displayButton(8, vid.yres-8-fs*11, XLAT("F1 = help"), SDLK_F1, 0);
displayButton(8, vid.yres-8-fs*10, XLAT("F2 = save"), SDLK_F2, 0);
displayButton(8, vid.yres-8-fs*9, XLAT("F3 = load"), SDLK_F3, 0);
@ -621,7 +621,9 @@ namespace mapeditor {
displayButton(8, vid.yres-8-fs*7, XLAT("F5 = restart"), SDLK_F5, 0);
displayButton(8, vid.yres-8-fs*6, XLAT("F6 = HQ shot"), SDLK_F6, 0);
displayButton(8, vid.yres-8-fs*5, XLAT("F7 = player on/off"), SDLK_F7, 0);
#if CAP_SVG
displayButton(8, vid.yres-8-fs*4, XLAT("F8 = SVG shot"), SDLK_F8, 0);
#endif
displayButton(8, vid.yres-8-fs*3, XLAT("SPACE = map/graphics"), ' ', 0);
displayButton(8, vid.yres-8-fs*2, XLAT("ESC = return to the game"), SDLK_ESCAPE, 0);
}
@ -793,7 +795,7 @@ namespace mapeditor {
cmode = sm::MAP;
gamescreen(0);
int fs = vid.fsize + 5;
int fs = min(vid.fsize + 5, vid.yres/26);
getcstat = '-';
@ -1130,7 +1132,7 @@ namespace mapeditor {
// left-clicks are coded with '-', and right-clicks are coded with sym F1
if(uni == '-') undoLock();
if(mousepressed && mouseover && sym != SDLK_F1)
if(uni == '-' && mouseover)
allInPattern(mouseover, radius, neighborId(mouseover, mouseover2));
if(mouseover) for(int i=0; i<mouseover->type; i++) createMov(mouseover, i);
@ -1262,22 +1264,6 @@ namespace mapeditor {
}
}
queueline(drawtrans*ccenter, drawtrans*coldcenter, darkena(0xC0C0C0, 0, 0x20));
int sg = drawcellShapeGroup();
if(0) for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i) && usershapes[sg][i]) {
usershapelayer &ds(usershapes[sg][i]->d[mapeditor::dslayer]);
for(int a=0; a<size(ds.list); a++) {
hyperpoint P2 = drawtrans * ds.list[a];
queuechr(P2, 10, 'x',
darkena(a == 0 ? 0x00FF00 :
a == size(ds.list)-1 ? 0xFF0000 :
0xFFFF00, 0, 0xFF));
}
}
}
void drawHandleKey(int sym, int uni);
@ -1323,7 +1309,7 @@ namespace mapeditor {
usershape *us =usershapes[drawcellShapeGroup()][drawcellShapeID()];
int fs = vid.fsize + 5;
int fs = min(vid.fsize + 5, vid.yres/28);
// displayButton(8, 8+fs*9, XLAT("l = lands"), 'l', 0);
displayfr(8, 8+fs, 2, vid.fsize, line1, 0xC0C0C0, 0);
@ -1353,11 +1339,12 @@ namespace mapeditor {
}
else {
displayfr(8, 8+fs*5, 2, vid.fsize, XLAT("'n' to start"), 0xC0C0C0, 0);
mousekey = 'n';
displaymm('n', 8, 8+fs*5, 2, vid.fsize, XLAT("'n' to start"), 0);
if(mousekey == 'a' || mousekey == 'd' || mousekey == 'd' ||
mousekey == 'c') mousekey = 'n';
}
displaymm('e', vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 16);
displaymm('g', vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 16);
displayButton(vid.xres-8, 8+fs*3, XLAT("z = zoom in"), 'z', 16);
displayButton(vid.xres-8, 8+fs*2, XLAT("o = zoom out"), 'o', 16);
displaymm('e', vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 16);
@ -1580,7 +1567,7 @@ namespace mapeditor {
for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i))
applyToShape(sg, i, uni, mh);
if(uni == 'e') {
if(uni == 'e' || (uni == '-' && mousekey == 'e')) {
initdraw(mouseover ? mouseover : cwt.c);
}
if(uni == 'l') { dslayer++; dslayer %= USERLAYERS; }
@ -1701,10 +1688,12 @@ namespace mapeditor {
saveHighQualityShot();
}
#endif
#if CAP_SVG
if(sym == SDLK_F8) {
svg::render();
}
#endif
if(sym == SDLK_F5) {
for(int i=0; i<USERSHAPEGROUPS; i++)
@ -1873,7 +1862,7 @@ namespace mapeditor {
}
bool drawUserShape(transmatrix V, int group, int id, int color, cell *c) {
#if ISMOBILE==1
#if !CAP_EDIT
return false;
#else
@ -1888,7 +1877,6 @@ namespace mapeditor {
}
}
#if CAP_EDIT
if((cmode & sm::DRAW) && mapeditor::editingShape(group, id)) {
/* for(int a=0; a<size(ds.list); a++) {
@ -1985,7 +1973,6 @@ namespace mapeditor {
}
}
#endif
return us;
#endif

219
menus.cpp
View File

@ -520,55 +520,6 @@ void showChangeMode() {
};
}
// -- cheat menu --
void showCheatMenu() {
gamescreen(1);
dialog::init("cheat menu");
dialog::addItem(XLAT("return to the game"), ' ');
dialog::addBreak(50);
dialog::addItem(XLAT("gain orb powers"), 'F');
dialog::addItem(XLAT("summon treasure"), 'T');
dialog::addItem(XLAT("summon dead orbs"), 'D');
dialog::addItem(XLAT("lose all treasure"), 'J');
dialog::addItem(XLAT("gain kills"), 'K');
dialog::addItem(XLAT("Hyperstone Quest"), 'C');
dialog::addItem(XLAT("summon orbs"), 'O');
dialog::addItem(XLAT("gain Orb of Yendor"), 'Y');
dialog::addItem(XLAT("summon lots of treasure"), 'T'-64);
dialog::addItem(XLAT("Safety (quick save)"), 'S');
dialog::addItem(XLAT("Select the land ---"), 'L');
dialog::addItem(XLAT("--- and teleport there"), 'U');
dialog::addItem(XLAT("rotate the character"), 'Z');
dialog::addItem(XLAT("summon a Golem"), 'G');
dialog::addItem(XLAT("summon Sandworm"), 'W');
dialog::addItem(XLAT("summon Ivy"), 'I');
dialog::addItem(XLAT("summon a Monster"), 'E');
dialog::addItem(XLAT("summon Thumpers"), 'H');
dialog::addItem(XLAT("summon Bonfire"), 'B');
dialog::addItem(XLAT("summon Mimics"), 'M');
dialog::addItem(XLAT("deplete orb powers"), 'P');
dialog::addItem(XLAT("summon Orb of Yendor"), 'Y'-64);
dialog::addItem(XLAT("switch ghost timer"), 'G'-64);
dialog::addItem(XLAT("switch web display"), 'W'-64);
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni != 0) {
applyCheat(uni);
if(uni == 'F' || uni == 'C' || uni == 'O' ||
uni == 'S' || uni == 'U' || uni == 'G' ||
uni == 'W' || uni == 'I' || uni == 'E' ||
uni == 'H' || uni == 'B' || uni == 'M' ||
uni == 'P' || uni == 'Y'-64 || uni == 'G'-64 ||
uni == ' ' || uni == 8 || uni == 13 ||
uni == SDLK_ESCAPE || uni == 'q' || uni == 'v' || sym == SDLK_ESCAPE ||
sym == SDLK_F10)
popScreen();
}
};
}
// -- geometry menu --
int eupage = 0;
@ -653,8 +604,8 @@ void showEuclideanMenu() {
if(eupage * euperpage >= LAND_SPHEUC) eupage = 0;
}
else if(lid >= 0 && lid < LAND_SPHEUC) {
euclidland = land_spheuc[lid];
if(landvisited[euclidland] && euclidland != laOceanWall) {
specialland = land_spheuc[lid];
if(landvisited[specialland] && specialland != laOceanWall) {
if(targetgeometry != geometry)
restartGame('g');
else
@ -662,7 +613,7 @@ void showEuclideanMenu() {
// disable PTM if chosen a land from the Euclidean menu
if(tactic::on) restartGame('t');
}
else euclidland = laIce;
else specialland = laIce;
}
else if(uni == '2' || sym == SDLK_F1) gotoHelp(
"If you want to know how much the gameplay is affected by the "
@ -725,42 +676,140 @@ void showDemo() {
dialog::addItem(XLAT("Burial Grounds"), 'b');
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(sym == SDLK_F1 || sym == 'h') gotoHelp(help);
else if(sym == 'a') {
toggleanim(!demoanim);
popScreen();
}
else if(sym == 'f') {
firstland = laIce;
if(tactic::on) restartGame('t');
else restartGame();
}
else if(sym == 'T') {
firstland = laIce;
if(!tour::on) tour::start();
}
else if(sym == 't') {
firstland = laTemple;
if(!tactic::on) restartGame('t');
else restartGame();
}
else if(sym == 'l') {
firstland = laStorms;
if(!tactic::on) restartGame('t');
else restartGame();
}
else if(sym == 'b') {
firstland = laBurial;
if(!tactic::on) restartGame('t');
else restartGame();
items[itOrbSword] = 60;
}
}
}
void handleDemoKey(int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(sym == SDLK_F1 || sym == 'h') gotoHelp(help);
else if(sym == 'a') {
toggleanim(!demoanim);
popScreen();
}
else if(sym == 'f') {
firstland = laIce;
if(tactic::on) restartGame('t');
else restartGame();
}
else if(sym == 'T') {
firstland = laIce;
if(!tour::on) tour::start();
}
else if(sym == 't') {
firstland = laTemple;
if(!tactic::on) restartGame('t');
else restartGame();
}
else if(sym == 'l') {
firstland = laStorms;
if(!tactic::on) restartGame('t');
else restartGame();
}
else if(sym == 'b') {
firstland = laBurial;
if(!tactic::on) restartGame('t');
else restartGame();
items[itOrbSword] = 60;
}
}
#endif
bool showstartmenu;
void showStartMenu() {
gamescreen(2);
getcstat = ' ';
dialog::init();
dialog::addInfo(XLAT("Welcome to HyperRogue!"));
dialog::addBreak(100);
dialog::addBigItem(XLAT("HyperRogue classic"), 'c');
dialog::addInfo(XLAT("explore the world, collect treasures"));
dialog::addInfo(XLAT("do not get checkmated"));
#if CAP_INV
dialog::addBreak(100);
dialog::addBigItem(XLAT("Orb Strategy mode"), 'i');
dialog::addInfo(XLAT("use your Orbs in tough situations"));
#endif
#if CAP_SHMUP
dialog::addBreak(100);
dialog::addBigItem(XLAT("shoot'em up mode"), 's');
dialog::addInfo(XLAT("continuous spacetime"));
#if HAVE_ACHIEVEMENTS
dialog::addInfo(XLAT("(most achievements are not available)"));
#endif
#endif
#if CAP_TOUR
dialog::addBreak(100);
dialog::addBigItem(XLAT("tutorial"), 't');
dialog::addInfo(XLAT("learn about hyperbolic geometry!"));
#endif
#if CAP_ROGUEVIZ && CAP_TOUR
dialog::addBreak(100);
dialog::addBigItem(XLAT("RogueViz"), 'r');
dialog::addInfo(XLAT("see the visualizations"));
#endif
dialog::addBreak(100);
dialog::addBigItem(XLAT("main menu"), 'm');
dialog::addInfo(XLAT("more options"));
dialog::display();
clearMessages();
/*
initquickqueue();
int siz = min(vid.xres, vid.yres) / 8;
drawMonsterType(moPrincess, NULL, atscreenpos(siz,siz,siz) * spin(-M_PI/4), 0, 0);
drawMonsterType(moKnight, NULL, atscreenpos(vid.xres-siz,siz,siz) * spin(-3*M_PI/4), 0, 0);
drawItemType(itOrbYendor, NULL, atscreenpos(siz,vid.yres-siz,siz) * spin(M_PI/4), iinf[itOrbYendor].color, 0, false);
drawItemType(itKey, NULL, atscreenpos(siz,vid.yres-siz,siz) * spin(M_PI/4), iinf[itKey].color, 0, false);
drawItemType(itHyperstone, NULL, atscreenpos(vid.xres-siz,vid.yres-siz,siz) * spin(3*M_PI/4), iinf[itHyperstone].color, 0, false);
quickqueue();
*/
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni == 'o') uni = 'i';
if(uni == 'c' || uni == 'i' || uni == 's') {
popScreenAll();
if(inv::on != (uni == 'i')) restartGame('i');
if(shmup::on != (uni == 's')) restartGame('S');
clearMessages();
welcomeMessage();
}
#if CAP_TOUR
else if(uni == 't') {
popScreenAll();
tour::start();
}
#endif
#if CAP_ROGUEVIZ && CAP_TOUR
else if(uni == 'r') {
tour::slides = rvtour::rvslides;
popScreenAll();
tour::start();
}
#endif
else if(sym == 'm') {
popScreen();
pushScreen(showMainMenu);
}
else if(sym == SDLK_F10)
quitmainloop = true;
else if(sym == SDLK_F1)
gotoHelp(help);
else if(sym == SDLK_ESCAPE || sym == ' ')
popScreen();
};
}
// -- overview --

View File

@ -273,7 +273,7 @@ hint hints[] = {
},
[] () {
if(!sphere) {
euclidland = laHalloween;
specialland = laHalloween;
targetgeometry = gSphere;
restartGame('E');
vid.alpha = 999;

View File

@ -1343,11 +1343,11 @@ void init() {
autocheat = true;
#if !ISWEB
mapeditor::drawplayer = false;
firstland = euclidland = laCanvas;
firstland = specialland = laCanvas;
if(!shmup::on) restartGame('s');
else restartGame();
#else
firstland = euclidland = laCanvas;
firstland = specialland = laCanvas;
restartGame();
#endif
on = true;
@ -1849,11 +1849,11 @@ slide rvslides[] = {
,
[] (presmode mode) {
slidecommand = "the standard presentation";
if(mode == pmStartAll) firstland = euclidland = laPalace;
if(mode == pmStartAll) firstland = specialland = laPalace;
if(mode == 4) {
tour::slides = default_slides;
while(tour::on) restartGame('T', false);
firstland = euclidland = laIce;
firstland = specialland = laIce;
tour::start();
}
}
@ -1976,7 +1976,7 @@ slide rvslides[] = {
{"THE END", 99, LEGAL_ANY | FINALSLIDE,
"Press '5' to leave the presentation.",
[] (presmode mode) {
firstland = euclidland = laIce;
firstland = specialland = laIce;
if(mode == 4) restartGame('T');
}
}

View File

@ -47,7 +47,7 @@ int modediff(score *S) {
if(S->box[196] != chaosmode) diff += 32;
if(S->box[119] != shmup::on) diff += 64;
if(pureHardcore() && !isHardcore(S)) diff += 128;
if(g != gNormal && S->box[120] != euclidland)
if(g != gNormal && S->box[120] != specialland)
diff += 256;
if(g != geometry) {
diff += 512;

View File

@ -23,6 +23,60 @@ bool verless(string v, string cmp) {
return v < cmp;
}
void welcomeMessage() {
if(tactic::trailer) return;
#if CAP_TOUR
else if(tour::on) return; // displayed by tour
#endif
else if(princess::challenge) {
kills[moVizier] = 1;
princess::forceMouse = true;
if(yendor::everwon)
items[itGreenStone] = 99;
addMessage(XLAT("Welcome to %the1 Challenge!", moPrincess));
addMessage(XLAT("The more Hypersian Rugs you collect, the harder it is.", moPrincess));
}
/* if(tactic::on && isCrossroads(firstland)) {
for(int i=0; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE && i != itHyperstone)
items[i] = 10;
kills[moYeti] = 1000;
} */
else if(randomPatternsMode)
addMessage(XLAT("Welcome to the Random Pattern mode!"));
else if(tactic::on)
addMessage(XLAT("You are playing %the1 in the Pure Tactics mode.", firstland));
else if(yendor::on)
addMessage(XLAT("Welcome to the Yendor Challenge %1!", its(yendor::challenge)));
else if(peace::on) ; // no welcome message
else if(shmup::on) ; // welcome message given elsewhere
else if(euclid)
addMessage(XLAT("Welcome to the Euclidean mode!"));
else if(sphere && specialland == laHalloween)
addMessage(XLAT("Welcome to Halloween!"));
else if(elliptic)
addMessage(XLAT("Good luck in the elliptic plane!"));
else if(sphere)
addMessage(XLAT("Welcome to Spherogue!"));
#if CAP_ROGUEVIZ
else if(rogueviz::on)
addMessage(XLAT("Welcome to RogueViz!"));
#endif
else {
addMessage(XLAT("Welcome to HyperRogue!"));
}
if(shmup::on && (specialland == laMirror || specialland == laMirrorOld) && (geometry == gElliptic || geometry == gQuotient))
addMessage(XLAT("This combination is known to be buggy at the moment."));
#if ISMAC
addMessage(XLAT("Press F1 or right-shift-click things for help."));
#elif !ISMOBILE
addMessage(XLAT("Press F1 or right-click things for help."));
#endif
}
// initialize the game
void initgame() {
DEBB(DF_INIT, (debugfile,"initGame\n"));
@ -34,9 +88,9 @@ void initgame() {
firstland = safetyland;
}
if(peace::on) euclidland = firstland = peace::whichland;
if(peace::on) firstland = specialland;
if(tactic::on && (euclid || sphere)) euclidland = firstland;
if(tactic::on && (euclid || sphere)) specialland = firstland;
if(firstland == laNone || firstland == laBarrier)
firstland = laCrossroads;
@ -48,7 +102,7 @@ void initgame() {
if(isGravityLand(firstland) && !tactic::on) firstland = laCrossroads;
cwt.c = currentmap->gamestart(); cwt.spin = 0; cwt.mirrored = false;
cwt.c->land = (euclid || sphere) ? euclidland : firstland;
cwt.c->land = (euclid || sphere) ? specialland : firstland;
chaosAchieved = false;
@ -92,7 +146,7 @@ void initgame() {
for(int i=0; i<65536; i++) euland[i] = laNone;
if(euclid && euclidland == laPrincessQuest) {
if(euclid && specialland == laPrincessQuest) {
cell *c = euclideanAtCreate(EPX, EPY);
princess::generating = true;
c->land = laPalace;
@ -198,56 +252,7 @@ void initgame() {
if(!randomPatternsMode && !tactic::on && !yendor::on && !peace::on) {
if(firstland != (princess::challenge ? laPalace : laIce)) cheater++;
}
if(tactic::trailer) ;
#if CAP_TOUR
else if(tour::on) ; // displayed by tour
#endif
else if(princess::challenge) {
kills[moVizier] = 1;
princess::forceMouse = true;
if(yendor::everwon)
items[itGreenStone] = 99;
addMessage(XLAT("Welcome to %the1 Challenge!", moPrincess));
addMessage(XLAT("The more Hypersian Rugs you collect, the harder it is.", moPrincess));
}
/* if(tactic::on && isCrossroads(firstland)) {
for(int i=0; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE && i != itHyperstone)
items[i] = 10;
kills[moYeti] = 1000;
} */
else if(randomPatternsMode)
addMessage(XLAT("Welcome to the Random Pattern mode!"));
else if(tactic::on)
addMessage(XLAT("You are playing %the1 in the Pure Tactics mode.", firstland));
else if(yendor::on)
addMessage(XLAT("Welcome to the Yendor Challenge %1!", its(yendor::challenge)));
else if(peace::on) ; // no welcome message
else if(shmup::on) ; // welcome message given elsewhere
else if(euclid)
addMessage(XLAT("Welcome to the Euclidean mode!"));
else if(sphere && euclidland == laHalloween)
addMessage(XLAT("Welcome to Halloween!"));
else if(elliptic)
addMessage(XLAT("Good luck in the elliptic plane!"));
else if(sphere)
addMessage(XLAT("Welcome to Spherogue!"));
#if CAP_ROGUEVIZ
else if(rogueviz::on)
addMessage(XLAT("Welcome to RogueViz!"));
#endif
else {
addMessage(XLAT("Welcome to HyperRogue!"));
#if ISMAC
addMessage(XLAT("Press F1 or right-shift-click things for help."));
#elif !ISMOBILE
addMessage(XLAT("Press F1 or right-click things for help."));
#endif
}
if(shmup::on && (euclidland == laMirror || euclidland == laMirrorOld) && (geometry == gElliptic || geometry == gQuotient))
addMessage(XLAT("This combination is known to be buggy at the moment."));
welcomeMessage();
}
else {
usedSafety = true;
@ -456,8 +461,8 @@ void applyBoxes() {
applyBoxBool(hardcore, "hardcore");
applyBoxNum(hardcoreAt, "");
applyBoxBool(shmup::on, "shmup");
if(saving) applyBoxSave(euclidland, "euclid land");
else if(loading) euclidland = eLand(applyBoxLoad("euclid land"));
if(saving) applyBoxSave(specialland, "euclid land");
else if(loading) specialland = eLand(applyBoxLoad("euclid land"));
else fakebox[boxid++] = true;
applyBoxI(itCoast);
@ -931,6 +936,13 @@ void loadsave() {
safety = true;
if(items[itSavedPrincess] < 0) items[itSavedPrincess] = 0;
addMessage(XLAT("Game loaded."));
showstartmenu = false;
// reset unsavable special modes just in case
peace::on = false;
randomPatternsMode = false;
yendor::on = false;
tactic::on = false;
tour::on = false;
}
}
#endif
@ -1133,326 +1145,6 @@ void restartGame(char switchWhat, bool push) {
resetmusic();
}
static int orbid = 0;
eItem nextOrb() {
orbid++;
eItem i = eItem(orbid % ittypes);
if(itemclass(i) == IC_ORB) return i;
else return nextOrb();
}
eItem randomTreasure() {
eItem i = eItem(hrand(ittypes));
if(itemclass(i) == IC_TREASURE) return i;
else return randomTreasure();
}
eItem randomTreasure2(int cv) {
int bq = 60000, cq = 0;
eItem best = itDiamond;
eItem lt = localTreasureType();
for(int a=1; a<ittypes; a++) {
eItem i = eItem(a);
if(itemclass(i) != IC_TREASURE) continue;
int q = 2*items[i];
if(a == lt) q -= (2*cv-1);
if(a == itEmerald && bearsCamelot(cwt.c->land)) q -= 8;
if(a == itElixir && isCrossroads(cwt.c->land)) q -= 7;
if(a == itIvory && isCrossroads(cwt.c->land)) q -= 6;
if(a == itPalace && isCrossroads(cwt.c->land)) q -= 5;
if(a == itIvory && cwt.c->land == laJungle) q -= 5;
if(a == itIvory && cwt.c->land == laPalace) q -= 5;
if(q < bq) bq = q, cq = 0;
if(q == bq) { cq++; if(hrand(cq) == 0) best = i; }
}
return best;
}
bool isTechnicalLand(eLand l) {
return l == laNone || l == laOceanWall || l == laBarrier || l == laCanvas ||
l == laHauntedWall || l == laHauntedBorder || l == laCA ||
l == laMirrorWall || l == laMirrored;
}
eLand cheatdest;
void cheatMoveTo(eLand l) {
cheatdest = l;
if(l == laCrossroads5) l = laCrossroads;
activateSafety(l);
cheatdest = laNone;
}
bool applyCheat(char u, cell *c = NULL) {
if(u == 'G') {
addMessage(XLAT("You summon a golem!"));
cheater++;
int i = cwt.spin;
if(passable(cwt.c->mov[i], NULL, 0))
cwt.c->mov[i]->monst = hrand(2) ? moGolem : moTameBomberbird;
return true;
}
if(u == 'L') {
do {
if(firstland == eLand(landtypes-1))
firstland = eLand(2);
else
firstland = eLand(firstland+1);
}
while(isTechnicalLand(firstland) || isCyclic(firstland));
euclidland = firstland;
cheater++; addMessage(XLAT("You will now start your games in %1", firstland));
return true;
}
if(u == 'C') {
cheater++;
cheatMoveTo(laCrossroads);
addMessage(XLAT("Activated the Hyperstone Quest!"));
for(int t=1; t<ittypes; t++)
if(t != itHyperstone && t != itBounty && itemclass(eItem(t)) == IC_TREASURE) {
items[t] = 10;
}
kills[moYeti] = 200;
kills[moDesertman] = 200;
kills[moRunDog] = 200;
kills[moZombie] = 200;
kills[moMonkey] = 200;
kills[moCultist] = 200;
kills[moTroll] = 200;
return true;
}
if(u == 'P') {
for(int i=0; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_ORB)
items[i] = 0;
cheater++; addMessage(XLAT("Orb power depleted!"));
return true;
}
if(u == 'O') {
cheater++; addMessage(XLAT("Orbs summoned!"));
for(int i=0; i<cwt.c->type; i++)
if(passable(cwt.c->mov[i], NULL, 0)) {
eItem it = nextOrb();
cwt.c->mov[i]->item = it;
}
return true;
}
if(u == 'F') {
if(hardcore && !canmove) {
canmove = true;
addMessage(XLAT("Revived!"));
}
else {
items[itOrbFlash] += 1;
items[itOrbTeleport] += 1;
items[itOrbLightning] += 1;
items[itOrbSpeed] += 1;
items[itOrbShield] += 1;
cheater++; addMessage(XLAT("Orb power gained!"));
canmove = true;
}
return true;
}
if(u == 'D') {
items[itGreenStone] += 10;
cheater++; addMessage(XLAT("Dead orbs gained!"));
return true;
}
if(u == 'R'-64) buildRosemap();
#if CAP_EDIT
if(u == 'A') {
lastexplore = turncount;
pushScreen(mapeditor::showMapEditor);
return true;
}
if(u == 'A'-64) {
mapeditor::drawcell = mouseover ? mouseover : cwt.c;
pushScreen(mapeditor::showDrawEditor);
return true;
}
#endif
if(u == 'Y') {
items[itOrbYendor] ++;
cheater++; addMessage(XLAT("Orb of Yendor gained!"));
return true;
}
if(u == 'T') {
items[randomTreasure2(10)] += 10;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'T'-64) {
items[randomTreasure2(100)] += 100;
cheater++; addMessage(XLAT("Lots of treasure gained!"));
return true;
}
if(u == 'I'-64) {
items[randomTreasure2(10)] += 25;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'U'-64) {
items[randomTreasure2(10)] += 50;
cheater++; addMessage(XLAT("Treasure gained!"));
return true;
}
if(u == 'W') {
addMessage(XLAT("You summon a sandworm!"));
cheater++;
int i = cwt.spin;
if(passable(cwt.c->mov[i], NULL, 0))
cwt.c->mov[i]->monst = moWorm,
cwt.c->mov[i]->mondir = NODIR;
return true;
}
if(u == 'I') {
addMessage(XLAT("You summon an Ivy!"));
cheater++;
int i = cwt.spin;
int j = cwt.c->spn(i);
cell* c = cwt.c->mov[i]->mov[(j+3)%cwt.c->mov[i]->type];
if(passable(c, NULL, 0)) buildIvy(c, 0, 1);
return true;
}
if(u == 'E') {
addMessage(XLAT("You summon a monster!"));
cheater++;
int i = cwt.spin;
if(cwt.c->mov[i]->wall == waChasm)
cwt.c->mov[i]->wall = waNone;
if(passable(cwt.c->mov[i], NULL, P_MONSTER)) {
eMonster mo[9] = { moEagle, moPyroCultist, moGhost, moTroll, moMiner, moVineBeast, moBug0,
moBomberbird, moSkeleton };
cwt.c->mov[i]->monst = mo[hrand(9)];
cwt.c->mov[i]->stuntime = 3;
cwt.c->mov[i]->hitpoints = 3;
}
return true;
}
if(u == 'E'-64) {
if(geometry) {
restartGame(0, false);
}
else {
euclidland = cwt.c->land;
printf("target geometry = %d\n", targetgeometry);
restartGame('g', true);
}
return true;
}
if(u == 'H') {
addMessage(XLAT("You summon some Thumpers!"));
cheater++;
for(int i=0; i<cwt.c->type; i++)
if(passable(cwt.c->mov[i], NULL, 0)) {
eWall ws[3] = { waThumperOff, waBigStatue, waBoat };
cwt.c->mov[i]->wall = ws[hrand(3)];
}
return true;
}
if(u == 'B') {
addMessage(XLAT("You summon a bonfire!"));
cheater++;
int i = cwt.spin;
if(passable(cwt.c->mov[i], NULL, 0))
cwt.c->mov[i]->wall = waBonfireOff;
return true;
}
if(u == 'Z') {
flipplayer = false;
mirror::act(1, mirror::SPINSINGLE);
cwspin(cwt, 1);
return true;
}
if(u == 'J') {
if(items[localTreasureType()] > 0)
items[localTreasureType()] = 0;
else for(int i=1; i<ittypes; i++)
if(itemclass(eItem(i)) == IC_TREASURE)
items[i] = 0;
cheater++; addMessage(XLAT("Treasure lost!"));
return true;
}
if(u == 'K') {
for(int i=0; i<motypes; i++) kills[i] += 10;
kills[moPlayer] = 0;
cheater++; addMessage(XLAT("Kills gained!"));
return true;
}
if(u == 'S') {
canmove = true;
cheatMoveTo(cwt.c->land);
items[itOrbSafety] += 3;
cheater++; addMessage(XLAT("Activated Orb of Safety!"));
return true;
}
if(u == 'U') {
canmove = true;
cheatMoveTo(firstland);
cheater++; addMessage(XLAT("Teleported to %1!", firstland));
return true;
}
if(u == 'W'-64) {
pushScreen(linepatterns::showMenu);
return true;
}
if(u == 'G'-64) {
timerghost = !timerghost;
cheater++;
addMessage(XLAT("turn count = %1 last exploration = %2 ghost timer = %3",
its(turncount), its(lastexplore), ONOFF(timerghost)));
return true;
}
if(u == 'F'-64) {
items[itOrbShield] += 30;
return true;
}
if(u == 'Y'-64) {
int i = cwt.spin;
cwt.c->mov[i]->item = itOrbYendor;
return true;
}
if(u == 'B'-64) {
int i = cwt.spin;
sword::angle[0]++;
cwt.c->mov[i]->item = hrand(2) ? itOrbSword2 : itOrbSword;
return true;
}
if(u == 'X'-64) {
items[itOrbNature] += 50;
cheater++;
return true;
}
if(u == 'V'-64) {
viewdists = !viewdists;
return true;
}
if(u == 'L'-64) {
cell *c = mouseover;
describeCell(c);
printf("Neighbors:"); for(int i=0; i<c->type; i++) printf("%p ", c->mov[i]);
printf("Barrier: dir=%d left=%d right=%d\n",
c->bardir, c->barleft, c->barright);
return true;
}
if(u == 'C'-64) {
cblind = !cblind;
return true;
}
if(u == 'P'-64)
peace::on = !peace::on;
#ifdef CHEAT_DISABLE_ALLOWED
if(u == 'D'-64) {
cheater = 0; autocheat = 0;
return true;
}
#endif
return false;
}
purehookset clearmemory;
void clearMemory() {

View File

@ -150,7 +150,7 @@ bool handleKeyTour(int sym, int uni) {
if(sym == '1') targetgeometry = gSphere;
if(sym == '2') targetgeometry = gEuclid;
firstland = euclidland = cwt.c->land;
firstland = specialland = cwt.c->land;
restartGame(sym == '3' ? '7' : 'g', true);
presentation(pmGeometryStart);
return true;
@ -289,7 +289,7 @@ void start() {
if(!tour::on) presentation(pmStartAll);
else {
presentation(pmStop);
firstland = euclidland = laIce;
firstland = specialland = laIce;
}
restartGame('T');
if(tour::on) {
@ -299,6 +299,25 @@ void start() {
}
slide default_slides[] = {
#if ISMOBILE
{"Note for mobiles", 10, LEGAL_ANY | QUICKSKIP,
"This tutorial is designed for computers, "
"and keys are given for all actions. It will "
"work without a keyboard though, although less "
"comfortably -- just ignore the keys "
"given and select options from MENU.\n\n"
"Select 'next slide' from MENU.",
[] (presmode mode) {
if(mode == pmStartAll) firstland = specialland = laIce;
if(mode == 1) {
if(tour::texts) addMessage(XLAT("Welcome to the HyperRogue tutorial!"));
else clearMessages();
}
SHOWLAND( l == laIce );
}
},
#endif
{"Introduction", 10, LEGAL_ANY | QUICKSKIP,
"This tutorial is mostly aimed to show what is "
"special about the geometry used by HyperRogue. "
@ -309,7 +328,7 @@ slide default_slides[] = {
"press ESC to see a "
"menu with other options.",
[] (presmode mode) {
if(mode == pmStartAll) firstland = euclidland = laIce;
if(mode == pmStartAll) firstland = specialland = laIce;
if(mode == 1) {
if(tour::texts) addMessage(XLAT("Welcome to the HyperRogue tutorial!"));
else clearMessages();

View File

@ -3,7 +3,7 @@
// basic utility functions
#if ISMOBILE || ISWEB || ISPANDORA
#if ISMOBILE || ISWEB || ISPANDORA || 1
typedef double ld;
#define LDF "%lf"
#define PLDF "lf"
@ -36,6 +36,8 @@ string llts(long long i) {
return llts(i/10) + its(i%10);
}
string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
string itsh2(int i) {static char buf[16]; sprintf(buf, "%02X", i); return buf; }
string itsh8(int i) {static char buf[16]; sprintf(buf, "%08X", i); return buf; }
// debug utilities

View File

@ -52,7 +52,7 @@ namespace yendor {
int challenge; // id of the challenge
int lastchallenge;
#define YENDORLEVELS 29
#define YENDORLEVELS 30
int bestscore[MODECODES][YENDORLEVELS];
@ -72,6 +72,7 @@ namespace yendor {
#define YF_START_CR 4096
#define YF_CHAOS 8192
#define YF_RECALL 16384
#define YF_NEAR_FJORD 32768
#define YF_START_ANY (YF_START_AL|YF_START_CR)
@ -109,6 +110,7 @@ namespace yendor {
{laDragon, YF_DEAD},
{laReptile, 0},
{laTortoise, YF_RECALL},
{laCocytus, YF_NEAR_FJORD}
};
int tscorelast;
@ -145,6 +147,8 @@ namespace yendor {
bool found;
bool foundOrb;
int howfar;
cell* key() { return path[YDIST-1]; }
cell* orb() { return path[0]; }
};
vector<yendorinfo> yi;
@ -324,7 +328,7 @@ namespace yendor {
won = false;
if(!easy) items[itOrbYendor] = bestscore[modecode()][challenge];
chaosmode = (clev().flags & YF_CHAOS);
euclidland = firstland = clev().l;
specialland = firstland = clev().l;
if(clev().flags & YF_START_AL) {
firstland = laAlchemist;
items[itElixir] = 50;
@ -337,6 +341,7 @@ namespace yendor {
}
if(firstland == laGraveyard) items[itBone] = 10;
if(firstland == laEmerald) items[itEmerald] = 10;
if(firstland == laCocytus) items[itFjord] = 10;
if(!euclid) {
if(clev().flags & YF_DEAD) items[itGreenStone] = 100;
if(clev().flags & YF_DEAD5) items[itGreenStone] = 5;
@ -361,6 +366,8 @@ namespace yendor {
yendor::check(c2);
if(clev().flags & YF_NEAR_IVY)
nexttostart = laJungle;
if(clev().flags & YF_NEAR_FJORD)
nexttostart = laLivefjord;
if(clev().flags & YF_NEAR_TENT)
nexttostart = laRlyeh;
if(clev().flags & YF_NEAR_ELEM) {
@ -404,6 +411,7 @@ namespace yendor {
if((ylev.flags & YF_NEAR_RED) && hiitemsMax(itRedGem) < 10) return false;
if((ylev.flags & YF_NEAR_OVER) && hiitemsMax(itMutant) < 10) return false;
if((ylev.flags & YF_NEAR_TENT) && hiitemsMax(itStatue) < 10) return false;
if((ylev.flags & YF_NEAR_FJORD) && hiitemsMax(itFjord) < 10) return false;
if((ylev.flags & YF_CHAOS) && !chaosUnlocked) return false;
if((ylev.flags & (YF_DEAD|YF_DEAD5)) && hiitemsMax(itBone) < 10) return false;
if((ylev.flags & YF_RECALL) && hiitemsMax(itSlime) < 10) return false;
@ -457,6 +465,7 @@ namespace yendor {
if(!euclid) {
if(ylev.flags & YF_CHAOS) { s = "Chaos mode"; }
if(ylev.flags & YF_NEAR_IVY) { s += "+"; s += XLATT1(laJungle); }
if(ylev.flags & YF_NEAR_FJORD) { s += "+"; s += XLATT1(laLivefjord); }
if(ylev.flags & YF_NEAR_TENT) { s += "+"; s += XLATT1(laRlyeh); }
if(ylev.flags & YF_NEAR_ELEM) { s += "+"; s += XLATT1(laElementalWall); }
if(ylev.flags & YF_NEAR_OVER) { s += "+"; s += XLATT1(laOvergrown); }
@ -744,7 +753,7 @@ namespace tactic {
keyhandler = [] (int sym, int uni) {
if(uni >= 1000 && uni < 1000 + LAND_TAC) {
firstland = euclidland = getLandById(uni - 1000);
firstland = specialland = getLandById(uni - 1000);
restartGame(tactic::on ? 0 : 't');
}
else if(uni == '0') {
@ -911,7 +920,6 @@ namespace peace {
bool hint = false;
bool otherpuzzles;
eLand whichland;
eLand simonlevels[] = {
laCrossroads, laCrossroads2, laDesert, laCaves, laAlchemist, laRlyeh, laEmerald,
@ -931,8 +939,15 @@ namespace peace {
eLand *levellist;
int qty;
void listLevels() {
levellist = otherpuzzles ? explorelevels : simonlevels;
for(qty = 0; levellist[qty]; qty++);
}
eLand getNext(eLand last) {
if(!peace::on) return laNone;
if(!qty) listLevels();
if(isElemental(last) && hrand(100) < 90)
return laNone;
else if(createOnSea(last))
@ -985,10 +1000,10 @@ namespace peace {
setdist(c, 5, NULL);
forCellEx(c2,c)
if(!eq(c2->aitmp, sval) && passable(c2, c, 0) && (c2->land == whichland || c2->land == laTemple) && !c2->item) {
if(!eq(c2->aitmp, sval) && passable(c2, c, 0) && (c2->land == specialland || c2->land == laTemple) && !c2->item) {
if(!id) fr = c2;
bool next;
if(whichland == laRlyeh)
if(specialland == laRlyeh)
next = c2->land == laTemple && (cp2->land == laRlyeh || celldistAlt(c2) < celldistAlt(cp2) - 8);
else
next = celldistance(c2, cp2) == 8;
@ -1038,14 +1053,13 @@ namespace peace {
path[i]->item = itDodeca, items[itDodeca]--;
}
}
void showMenu() {
listLevels();
dialog::init(XLAT(otherpuzzles ? "puzzles and exploration" : "memory game"), 0x40A040, 150, 100);
levellist = otherpuzzles ? explorelevels : simonlevels;
for(qty = 0; levellist[qty]; qty++)
dialog::addItem(XLAT1(linf[levellist[qty]].name), 'a'+qty);
for(int i = 0; i<qty; i++)
dialog::addItem(XLAT1(linf[levellist[i]].name), 'a'+i);
dialog::addBreak(100);
dialog::addItem(XLAT(otherpuzzles ? "memory game" : "puzzles and exploration"), '1');
@ -1060,7 +1074,7 @@ namespace peace {
if(uni == '1') otherpuzzles = !otherpuzzles;
else if(uni >= 'a' && uni < 'a' + qty) {
whichland = levellist[uni - 'a'];
specialland = levellist[uni - 'a'];
restartGame(peace::on ? 0 : 'P');
}
else if(uni == '2') { hint = !hint; popScreen(); }