mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-27 14:37:16 +00:00
10.0
This commit is contained in:
parent
2c88dfabd2
commit
ce5650a81f
@ -1,7 +1,7 @@
|
||||
// Hyperbolic Rogue -- achievements
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#define NUMLEADER 69
|
||||
#define NUMLEADER 70
|
||||
|
||||
#define SCORE_UNKNOWN (-1)
|
||||
#define NO_SCORE_YET (-2)
|
||||
@ -14,7 +14,7 @@ int currentscore[NUMLEADER];
|
||||
|
||||
const char* leadernames[NUMLEADER] = {
|
||||
"Score", "Diamonds", "Gold", "Spice", "Rubies", "Elixirs",
|
||||
"Shards", "Totems", "Daisies", "Statues", "Feathers", "Sapphires",
|
||||
"Shards100", "Totems", "Daisies", "Statues", "Feathers", "Sapphires",
|
||||
"Hyperstones", "Time to Win-71", "Turns to Win-71",
|
||||
"Time to 10 Hyperstones-94", "Turns to 10 Hyperstones-94", "Orbs of Yendor",
|
||||
"Fern Flowers",
|
||||
@ -58,7 +58,8 @@ const char* leadernames[NUMLEADER] = {
|
||||
"Slime Molds", // 65
|
||||
"Dodecahedra", // 66
|
||||
"Green Grass", // 67
|
||||
"Spinel" // 68
|
||||
"Spinel", // 68
|
||||
"Orb Strategy Score", // 69
|
||||
};
|
||||
|
||||
#define LB_STATISTICS 62
|
||||
@ -212,7 +213,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
||||
if(q == 8) achievement_gain("GRAIL4");
|
||||
}
|
||||
|
||||
if(q == 10) {
|
||||
if(q == U10) {
|
||||
if(it == itDiamond) achievement_gain("DIAMOND2");
|
||||
if(it == itRuby) achievement_gain("RUBY2");
|
||||
if(it == itHyperstone) achievement_gain("HYPER2");
|
||||
@ -268,7 +269,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
||||
if(it == itBull) achievement_gain("BULL2");
|
||||
}
|
||||
|
||||
if(q == 25) {
|
||||
if(q == R10) {
|
||||
if(it == itDiamond) achievement_gain("DIAMOND3");
|
||||
if(it == itRuby) achievement_gain("RUBY3");
|
||||
if(it == itHyperstone) achievement_gain("HYPER3");
|
||||
@ -327,7 +328,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
||||
if(it == itBull) achievement_gain("BULL3");
|
||||
}
|
||||
|
||||
if(q == 50) {
|
||||
if(q == 50 && !inv::on) {
|
||||
if(it == itDiamond) achievement_gain("DIAMOND4");
|
||||
if(it == itRuby) achievement_gain("RUBY4");
|
||||
if(it == itHyperstone) achievement_gain("HYPER4");
|
||||
@ -553,18 +554,21 @@ void achievement_final(bool really_final) {
|
||||
if(shmup::on) specials++;
|
||||
if(chaosmode) specials++;
|
||||
if(purehepta) specials++;
|
||||
if(inv::on) specials++;
|
||||
if(specials > 1) return;
|
||||
|
||||
if(numplayers() > 1 && chaosmode) return;
|
||||
if(numplayers() > 1 && purehepta) return;
|
||||
if(numplayers() > 1 && inv::on) return;
|
||||
|
||||
int total_improved = 0;
|
||||
specific_improved = 0;
|
||||
specific_what = 0;
|
||||
|
||||
if(!shmup::on && !chaosmode && !purehepta && numplayers() == 1) improveItemScores();
|
||||
if(!shmup::on && !chaosmode && !purehepta && numplayers() == 1 && !inv::on) improveItemScores();
|
||||
|
||||
int sid = purehepta ? 57 : chaosmode ? 53 : shmup::on ? (numplayers() > 1 ? 44 : 28) :
|
||||
inv::on ? 69 :
|
||||
(numplayers() > 1 ? 61 : 0);
|
||||
|
||||
int tg = gold();
|
||||
@ -601,6 +605,19 @@ void achievement_final(bool really_final) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool hadtotalvictory;
|
||||
|
||||
void check_total_victory() {
|
||||
if(!inv::on) return;
|
||||
if(hadtotalvictory) return;
|
||||
if(!items[itOrbYendor]) return;
|
||||
if(!items[itHolyGrail]) return;
|
||||
if(items[itHyperstone] < 50) return;
|
||||
if(!princess::saved) return;
|
||||
hadtotalvictory = true;
|
||||
achievement_gain("TOTALVICTORY");
|
||||
}
|
||||
|
||||
void achievement_victory(bool hyper) {
|
||||
DEBB(DF_STEAM, (debugfile,"achievement_victory\n"))
|
||||
if(offlineMode) return;
|
||||
|
@ -88,8 +88,6 @@ int textwidth(int siz, const string &str) {
|
||||
|
||||
#endif
|
||||
|
||||
int gradient(int c0, int c1, ld v0, ld v, ld v1);
|
||||
|
||||
int darkenedby(int c, int lev) {
|
||||
for(int i=0; i<lev; i++)
|
||||
c = ((c & 0xFEFEFE) >> 1);
|
||||
@ -100,6 +98,10 @@ int darkened(int c) {
|
||||
#ifdef EXTRA_FADEOUT
|
||||
c = gradient(backcolor, c, 0, extra::fadeout, 1);
|
||||
#endif
|
||||
if(inmirrorcount&1)
|
||||
c = gradient(c, winf[waMirror].color, 0, 0.5, 1);
|
||||
else if(inmirrorcount)
|
||||
c = gradient(c, winf[waCloud].color, 0, 0.5, 1);
|
||||
for(int i=0; i<darken; i++)
|
||||
c = ((c & 0xFEFEFE) >> 1) + ((backcolor & 0xFEFEFE) >> 1);
|
||||
return c;
|
||||
@ -1008,8 +1010,10 @@ void setvideomode() {
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 16);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
#ifndef MAC
|
||||
else
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
2
cell.cpp
2
cell.cpp
@ -648,7 +648,7 @@ struct cellwalker {
|
||||
cell *c;
|
||||
int spin;
|
||||
bool mirrored;
|
||||
cellwalker(cell *c, int spin) : c(c), spin(spin) { mirrored = false; }
|
||||
cellwalker(cell *c, int spin, bool m=false) : c(c), spin(spin), mirrored(m) { }
|
||||
cellwalker() { mirrored = false; }
|
||||
};
|
||||
|
||||
|
33
classes.cpp
33
classes.cpp
@ -1143,17 +1143,23 @@ itemtype iinf[ittypes] = {
|
||||
"Target a cell on the other side to use it."
|
||||
},
|
||||
{ '$', 0x80FF80, "Green Grass", prairiedesc },
|
||||
{ 'o', 0x8080FF, "Orb of Horns",
|
||||
{ 'o', 0xC09090, "Orb of Horns",
|
||||
"After you move while having this Orb, you immediately attack the next cell in the straight line "
|
||||
"(or two cells, when moving on a heptagon). This attack is slightly stronger than your normal "
|
||||
"attack: it can stun some of the monsters which cannot be killed or stunned normally."
|
||||
},
|
||||
{ 'o', 0x8080FF, "Orb of the Bull",
|
||||
{ 'o', 0xA05020, "Orb of the Bull",
|
||||
"You get the powers of Shield, Horns, and Thorns after you move two moves in a straight line "
|
||||
"with this Orb." },
|
||||
{ '$', 0xC060C0, "Spinel", bulldashdesc },
|
||||
{ 'o', 0xC0C0FF, "Orb of the Mirror", NODESCYET },
|
||||
{ 'O', 0xF0F0F0, "your orbs", NODESC},
|
||||
{ 'o', 0xC0C0FF, "Orb of the Mirror",
|
||||
"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.",
|
||||
},
|
||||
{ 'O', 0xF0F0F0, "your orbs",
|
||||
"Click this to see your orbs."},
|
||||
};
|
||||
|
||||
enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBone, itHell, itStatue,
|
||||
@ -1192,7 +1198,7 @@ enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBo
|
||||
|
||||
// --- wall types ---
|
||||
|
||||
const int walltypes = 97;
|
||||
const int walltypes = 98;
|
||||
|
||||
struct walltype {
|
||||
char glyph;
|
||||
@ -1372,6 +1378,7 @@ walltype winf[walltypes] = {
|
||||
{ '.', 0xFFFF00, "Reptile floor", reptiledesc},
|
||||
{ '.', 0xFFFF00, "Reptile bridge", reptiledesc},
|
||||
{ '.', 0xFFFF00, "invisible floor", NODESCYET},
|
||||
{ '#', 0xC0C0FF, "mirror wall", NODESCYET},
|
||||
};
|
||||
|
||||
enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCavefloor, waDeadTroll, waDune,
|
||||
@ -1400,12 +1407,13 @@ enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCav
|
||||
waPetrified, waTower,
|
||||
waBigBush, waSmallBush,
|
||||
waReptile, waReptileBridge,
|
||||
waInvisibleFloor
|
||||
waInvisibleFloor,
|
||||
waMirrorWall
|
||||
};
|
||||
|
||||
// --- land types ---
|
||||
|
||||
const int landtypes = 67;
|
||||
const int landtypes = 71;
|
||||
|
||||
struct landtype {
|
||||
int color;
|
||||
@ -1437,7 +1445,7 @@ const landtype linf[landtypes] = {
|
||||
"A land filled with huge ivy plants and dangerous animals."
|
||||
},
|
||||
{ 0x900090, "Alchemist Lab", slimehelp},
|
||||
{ 0x704070, "Mirror Land",
|
||||
{ 0x704070, "Hall of Mirrors",
|
||||
"A strange land which contains mirrors and mirages, protected by Mirror Rangers."},
|
||||
{ 0x404070, "Graveyard",
|
||||
"All the monsters you kill are carried to this strange land, and buried. "
|
||||
@ -1578,7 +1586,11 @@ const landtype linf[landtypes] = {
|
||||
{ 0x0000D0, "Prairie", prairiedesc},
|
||||
{ 0x800080, "Bull Dash", bulldashdesc},
|
||||
{ 0xC000C0, "Crossroads V", "Extremely narrow Crossroads layout.\n"},
|
||||
{ 0xC0C0C0, "Cellular Automaton", cadesc}
|
||||
{ 0xC0C0C0, "Cellular Automaton", cadesc},
|
||||
{ 0xC0C0FF, "Mirror Wall", NODESCYET},
|
||||
{ 0xC8C8FF, "Reflection", NODESCYET},
|
||||
{ 0xC0C0FF, "Reflection", NODESCYET},
|
||||
{ 0xC8C8FF, "Reflection", NODESCYET},
|
||||
};
|
||||
|
||||
enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle, laAlchemist, laMirror, laGraveyard,
|
||||
@ -1595,7 +1607,8 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle
|
||||
laEndorian, laTortoise, laDragon,
|
||||
laKraken, laBurial, laTrollheim,
|
||||
laHalloween, laDungeon, laMountain, laReptile,
|
||||
laPrairie, laBull, laCrossroads5, laCA
|
||||
laPrairie, laBull, laCrossroads5, laCA,
|
||||
laMirrorWall, laMirrored, laMirrorWall2, laMirrored2
|
||||
};
|
||||
|
||||
// cell information for the game
|
||||
|
222
complex.cpp
222
complex.cpp
@ -466,6 +466,8 @@ namespace princess {
|
||||
|
||||
#define OUT_OF_PRISON 200
|
||||
#define OUT_OF_PALACE 250
|
||||
#define PRADIUS0 (141)
|
||||
#define PRADIUS1 (150)
|
||||
|
||||
bool generating = false;
|
||||
bool challenge = false;
|
||||
@ -475,6 +477,8 @@ namespace princess {
|
||||
bool forceVizier = false;
|
||||
bool forceMouse = false;
|
||||
bool gotoPrincess = false;
|
||||
bool nodungeon = false;
|
||||
bool squeaked = false;
|
||||
|
||||
int saveHP = 0, saveArmedHP = 0;
|
||||
|
||||
@ -496,7 +500,7 @@ namespace princess {
|
||||
if(i->alt) i->alt->emeraldval = i->id;
|
||||
}
|
||||
|
||||
void newInfo(cell *c) {
|
||||
int newInfo(cell *c) {
|
||||
info *i = new info;
|
||||
i->prison = c;
|
||||
i->princess = c;
|
||||
@ -506,6 +510,7 @@ namespace princess {
|
||||
i->bestnear = OUT_OF_PRISON;
|
||||
infos.push_back(i);
|
||||
assign(i);
|
||||
return i->id;
|
||||
}
|
||||
|
||||
void newFakeInfo(cell *c) {
|
||||
@ -514,7 +519,7 @@ namespace princess {
|
||||
i->princess = c;
|
||||
i->alt = NULL;
|
||||
i->id = size(infos);
|
||||
i->bestdist = OUT_OF_PALACE;
|
||||
i->bestdist = items[itSavedPrincess] ? OUT_OF_PALACE : OUT_OF_PRISON;
|
||||
i->bestnear = 0;
|
||||
infos.push_back(i);
|
||||
assign(i);
|
||||
@ -524,7 +529,7 @@ namespace princess {
|
||||
if(euclid) return NULL;
|
||||
if(c->land != laPalace) return NULL;
|
||||
if(!c->master->alt) return NULL;
|
||||
int ev = c->master->alt->emeraldval; // NEWYEARFIX
|
||||
int ev = c->master->alt->alt->emeraldval; // NEWYEARFIX
|
||||
if(ev < 0 || ev >= size(infos)) return NULL;
|
||||
if(infos[ev]->alt != c->master->alt->alt) return NULL;
|
||||
return infos[ev];
|
||||
@ -535,6 +540,7 @@ namespace princess {
|
||||
while(i) {
|
||||
infos[i]->id = i-1; assign(infos[i]);
|
||||
infos[i-1]->id = i; assign(infos[i-1]);
|
||||
swap(infos[i], infos[i-1]);
|
||||
i--;
|
||||
}
|
||||
return infos[i];
|
||||
@ -543,7 +549,7 @@ namespace princess {
|
||||
}
|
||||
|
||||
int dist(cell *c) {
|
||||
if(c->land != laPalace) return OUT_OF_PALACE;
|
||||
if(c->land != laPalace && c->land != laDungeon) return OUT_OF_PALACE;
|
||||
else if(quotient || sphere || torus) return OUT_OF_PRISON;
|
||||
else if(euclid) return celldistAlt(c);
|
||||
else if(!c->master->alt) return OUT_OF_PRISON;
|
||||
@ -565,10 +571,10 @@ namespace princess {
|
||||
playSound(c, princessgender() ? "heal-princess" : "heal-prince");
|
||||
|
||||
info *inf = NULL;
|
||||
for(int i=0; i<size(infos); i++)
|
||||
if(infos[i]->princess && infos[i]->bestdist == OUT_OF_PALACE)
|
||||
for(int i=0; i<size(infos); i++) {
|
||||
if(infos[i]->princess && infos[i]->bestdist == OUT_OF_PALACE && isPrincess(infos[i]->princess->monst))
|
||||
inf = infos[i];
|
||||
|
||||
}
|
||||
if(inf) { inf->princess->monst = moNone; inf->princess = c; }
|
||||
else newFakeInfo(c);
|
||||
return true;
|
||||
@ -586,6 +592,9 @@ namespace princess {
|
||||
// printf("Improved dist to %d\n", newdist);
|
||||
if(newdist == OUT_OF_PALACE) {
|
||||
if(!princess::saved)
|
||||
#ifdef INV
|
||||
if(!inv::on || !inv::usedForbidden)
|
||||
#endif
|
||||
achievement_gain("PRINCESS1");
|
||||
princess::saved = true;
|
||||
princess::everSaved = true;
|
||||
@ -600,25 +609,27 @@ namespace princess {
|
||||
showMissionScreen();
|
||||
}
|
||||
}
|
||||
if(i->princess->land == laDungeon && !saved && !nodungeon) {
|
||||
addMessage(XLAT("%The1 says, \"not this place, it looks even worse...\"", moPrincess));
|
||||
nodungeon = true;
|
||||
}
|
||||
}
|
||||
|
||||
void save(cell *princess) {
|
||||
if(euclid) return;
|
||||
princess::info *i = princess::getPrincessInfo(princess);
|
||||
if(!i || i->bestdist <= 3) princess->monst = moNone;
|
||||
else if(i) setdist(i, OUT_OF_PALACE);
|
||||
else if(i) setdist(i, OUT_OF_PRISON);
|
||||
}
|
||||
|
||||
void move(cell *ct, cell *cf) {
|
||||
if(euclid) return;
|
||||
princess::info *i = princess::getPrincessInfo(cf);
|
||||
if(!i) {
|
||||
static bool warn = true;
|
||||
// note: OK if mapediting or loading
|
||||
if(warn) printf("Warning: unknown princess\n");
|
||||
if(warn && !cheater)
|
||||
printf("Warning: unknown princess\n");
|
||||
if(!cheater)
|
||||
addMessage("Warning: unknown princess (that's a bug, please report)");
|
||||
warn = false;
|
||||
}
|
||||
else {
|
||||
i->princess = ct;
|
||||
@ -661,31 +672,33 @@ namespace princess {
|
||||
retry:
|
||||
if(msgid >= 32) msgid = 0;
|
||||
|
||||
if(msgid == 0 && d < 20 && c->land == laPalace) {
|
||||
bool inpalace = c->land == laPalace || c->land == laDungeon;
|
||||
|
||||
if(msgid == 0 && d < 20 && inpalace) {
|
||||
addMessage(XLAT("%The1 kisses you, and begs you to bring %him1 away from here.", m));
|
||||
}
|
||||
else if(msgid == 1 && d >= 20 && c->land == laPalace) {
|
||||
else if(msgid == 1 && d >= 20 && inpalace) {
|
||||
if(m == moPrincess)
|
||||
addMessage(XLAT("\"I want my revenge. Stun a guard and leave him for me!\"", m));
|
||||
else
|
||||
addMessage(XLAT("\"That felt great. Thanks!\"", m));
|
||||
}
|
||||
else if(msgid == 2 && d >= 70 && c->land == laPalace) {
|
||||
else if(msgid == 2 && d >= 70 && inpalace) {
|
||||
addMessage(XLAT("\"Bring me out of here please!\"", m));
|
||||
}
|
||||
else if(msgid == 3 && c->land != laPalace) {
|
||||
else if(msgid == 3 && !inpalace) {
|
||||
addMessage(XLAT("%The1 kisses you, and thanks you for saving %him1.", m));
|
||||
}
|
||||
else if(msgid == 4 && c->land != laPalace && m == moPrincess) {
|
||||
else if(msgid == 4 && !inpalace && m == moPrincess) {
|
||||
addMessage(XLAT("\"I have been trained to fight with a Hypersian scimitar, you know?\"", m));
|
||||
}
|
||||
else if(msgid == 5 && c->land != laPalace) {
|
||||
else if(msgid == 5 && !inpalace) {
|
||||
addMessage(XLAT("\"I would love to come to your world with you!\"", m));
|
||||
}
|
||||
else if(msgid == 6 && c->land != laPalace) {
|
||||
else if(msgid == 6 && !inpalace) {
|
||||
addMessage(XLAT("\"Straight lines stay close to each other forever, this is so romantic!\"", m));
|
||||
}
|
||||
else if(msgid == 7 && c->land != laPalace) {
|
||||
else if(msgid == 7 && !inpalace) {
|
||||
addMessage(XLAT("\"Maps... Just like the world, but smaller... how is that even possible?!\"", m));
|
||||
}
|
||||
else {
|
||||
@ -1005,23 +1018,31 @@ namespace mirror {
|
||||
c->wall == waFrozenLake || c->wall == waDeadfloor || c->wall == waDeadfloor2 ||
|
||||
c->wall == waGiantRug || c->wall == waCIsland || c->wall == waCIsland2 ||
|
||||
c->wall == waGargoyleFloor || c->wall == waRubble ||
|
||||
c->wall == waGargoyleBridge || c->wall == waTempFloor || c->wall == waTempBridge;
|
||||
}
|
||||
|
||||
void createMM(cellwalker& cw, eMonster type) {
|
||||
if(type == moLightningBolt)
|
||||
castLightningBolt(cw);
|
||||
else if(cw.c->monst == moNone && cellMirrorable(cw.c) && !isPlayerOn(cw.c)) {
|
||||
cw.c->monst = type;
|
||||
cw.c->mondir = cw.spin;
|
||||
cw.c->hitpoints = multi::cpid;
|
||||
}
|
||||
c->wall == waGargoyleBridge || c->wall == waTempFloor || c->wall == waTempBridge ||
|
||||
c->wall == waMirrorWall;
|
||||
}
|
||||
|
||||
inline eMonster switchtype(eMonster m) {
|
||||
return (m == moMirror) ? moMirage : moMirror;
|
||||
}
|
||||
|
||||
void createMM(cellwalker& cw, eMonster type) {
|
||||
if(type == moLightningBolt) {
|
||||
castLightningBolt(cw);
|
||||
return;
|
||||
}
|
||||
if(inmirror(cw)) {
|
||||
bool b = cw.mirrored;
|
||||
cw = reflect(cw);
|
||||
if(cw.mirrored != b) type = switchtype(type);
|
||||
}
|
||||
if(cw.c->monst == moNone && cellMirrorable(cw.c) && !isPlayerOn(cw.c)) {
|
||||
cw.c->monst = type;
|
||||
cw.c->mondir = cw.spin;
|
||||
cw.c->hitpoints = multi::cpid;
|
||||
}
|
||||
}
|
||||
|
||||
inline eMonster switchtypeif(eMonster m, bool b) {
|
||||
if(!b) return m;
|
||||
return (m == moMirror) ? moMirage : moMirror;
|
||||
@ -1113,7 +1134,7 @@ namespace mirror {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void go(bool fwd) {
|
||||
int tk = tkills();
|
||||
int nummirage = 0;
|
||||
@ -1123,9 +1144,24 @@ namespace mirror {
|
||||
if(c->hitpoints != multi::cpid) continue;
|
||||
eMonster m = c->monst;
|
||||
if(isMimic(m)) {
|
||||
if(m == moMirage) nummirage++;
|
||||
|
||||
int dir = c->mondir;
|
||||
if(m == moMirage) nummirage++;
|
||||
cell *c2 = c->mov[dir];
|
||||
|
||||
if(c2 && inmirror(c2)) {
|
||||
if(c->land == laMirror) {
|
||||
// c->mondir = (dir+3) % 6;
|
||||
c->monst = switchtype(m);
|
||||
continue;
|
||||
}
|
||||
cellwalker cw(c2, c->spin(dir), false);
|
||||
cw = reflect(cw);
|
||||
dir = c->mondir = cw.c->spin(cw.spin);
|
||||
if(cw.mirrored) m = c->monst = switchtype(m);
|
||||
c2 = c->mov[dir];
|
||||
}
|
||||
|
||||
if(c2 && !isMimic(c2) && canAttack(c,m,c2,c2->monst, 0))
|
||||
attackMonster(c2, AF_MSG | AF_ORSTUN, m);
|
||||
if(c2->wall == waBigTree)
|
||||
@ -1135,7 +1171,7 @@ namespace mirror {
|
||||
if(!fwd) continue;
|
||||
c->monst = moNone;
|
||||
if(!c2) continue;
|
||||
if(!passable(c2, c, P_MONSTER | P_MIRROR)) continue;
|
||||
if(!passable(c2, c, P_MONSTER | P_MIRROR | P_MIRRORWALL)) continue;
|
||||
if(isWorm(c2)) continue;
|
||||
if(c2->monst == moGreater) {
|
||||
c2->monst = moLesser; continue;
|
||||
@ -1192,7 +1228,123 @@ namespace mirror {
|
||||
if(multi::players > 1) spin(d);
|
||||
go(fwd);
|
||||
}
|
||||
|
||||
int mirrordir(cell *c) {
|
||||
if(c->type == 7) return c->bardir;
|
||||
|
||||
int icount = 0, isum = 0;
|
||||
for(int i=0; i<6; i+=2) {
|
||||
if(createMov(c, i)->bardir == c->spin(i))
|
||||
icount++, isum+=i;
|
||||
}
|
||||
if(icount > 1) return -1;
|
||||
return isum;
|
||||
}
|
||||
|
||||
pair<bool, cellwalker> traceback(vector<int>& v, cellwalker cw) {
|
||||
bool goout = false;
|
||||
for(int i=size(v)-1; i>=0; i--) {
|
||||
if(v[i]) cwspin(cw, -v[i]);
|
||||
else {
|
||||
cwstep(cw);
|
||||
if(cw.c->land == laMirrorWall || cw.c->land == laMirror) goout = true;
|
||||
}
|
||||
}
|
||||
return make_pair(goout, cw);
|
||||
}
|
||||
|
||||
cellwalker reflect(cellwalker cw, bool debug) {
|
||||
int stepcount = 0;
|
||||
cellwalker cwcopy = cw;
|
||||
static vector<int> v;
|
||||
v.clear();
|
||||
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;
|
||||
if(go) {
|
||||
v.push_back(0);
|
||||
cwstep(cw);
|
||||
if(debug) queuemarkerat(gmatrix[cw.c], 0x00FF0020);
|
||||
if(go == 2) break;
|
||||
}
|
||||
else {
|
||||
v.push_back(1);
|
||||
cwspin(cw, 1);
|
||||
}
|
||||
}
|
||||
if(cw.c->land == laMirrorWall || cw.c->land == laMirrorWall2) {
|
||||
if(cw.c->type == 7) {
|
||||
while(cw.spin != cw.c->bardir) {
|
||||
cwspin(cw, 1);
|
||||
v.push_back(1);
|
||||
stepcount++; if(stepcount > 10000) { printf("failhep\n"); return cw; }
|
||||
}
|
||||
if(purehepta && cwpeek(cw,0) == cwcopy.c)
|
||||
v.pop_back();
|
||||
if(purehepta && cwpeek(cw,3)->land == laMirrored && cwpeek(cw,2)->land == laMirrorWall) {
|
||||
cw.mirrored = !cw.mirrored;
|
||||
auto p = traceback(v, cw);
|
||||
if(p.first) return p.second;
|
||||
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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(cwpeek(cw,0)->type != 7) {
|
||||
cwspin(cw, 1);
|
||||
v.push_back(1);
|
||||
}
|
||||
int icount = 0;
|
||||
for(int i=0; i<3; i++) {
|
||||
if(cwpeek(cw, 0)->bardir == cw.c->spin(cw.spin))
|
||||
icount++;
|
||||
cwspin(cw, 2);
|
||||
}
|
||||
if(icount >= 2) {
|
||||
cellwalker cwcopy = cw;
|
||||
for(int a=0; a<3; a++) for(int m=0; m<2; m++) {
|
||||
cellwalker cw = cwcopy;
|
||||
if(m) cw.mirrored = !cw.mirrored;
|
||||
cwspin(cw, a*2);
|
||||
auto p = traceback(v,cw);
|
||||
if(p.first) return p.second;
|
||||
}
|
||||
printf("icount >= 2 but failed\n");
|
||||
return cw;
|
||||
}
|
||||
while(cwpeek(cw, 0)->bardir != cw.c->spin(cw.spin)) {
|
||||
stepcount++; if(stepcount > 10000) { printf("fail2\n"); return cw; }
|
||||
cwspin(cw, 2);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else v.pop_back();
|
||||
cw.mirrored = !cw.mirrored;
|
||||
cw = traceback(v,cw).second;
|
||||
return cw;
|
||||
}
|
||||
|
||||
void debug() {
|
||||
if(!mouseover) return;
|
||||
queuemarkerat(gmatrix[mouseover], 0xFF0000FF);
|
||||
cellwalker mw(mouseover, (SDL_GetTicks()/1000) % mouseover->type, (SDL_GetTicks()/500) % 2);
|
||||
mw = mirror::reflect(mw, true);
|
||||
queuemarkerat(gmatrix[mw.c], 0x800000FF);
|
||||
}
|
||||
}
|
||||
|
||||
namespace hive {
|
||||
@ -2765,7 +2917,7 @@ namespace ca {
|
||||
}
|
||||
|
||||
auto ccm = addHook(clearmemory, 0, [] () {
|
||||
offscreen.clear();
|
||||
offscreen.clear();
|
||||
princess::clear();
|
||||
mirrors.clear();
|
||||
clearing::bpdata.clear();
|
||||
|
560
config.cpp
560
config.cpp
@ -45,43 +45,91 @@ int lang() {
|
||||
|
||||
bool autojoy = true;
|
||||
|
||||
/*struct saver {
|
||||
struct supersaver {
|
||||
string name;
|
||||
virtual string save();
|
||||
virtual void load(string& s);
|
||||
virtual string save() = 0;
|
||||
virtual void load(const string& s) = 0;
|
||||
virtual bool dosave() = 0;
|
||||
};
|
||||
|
||||
struct intsaver : saver {
|
||||
int& val;
|
||||
int dft;
|
||||
void intsaver() { val = dft; }
|
||||
string save() { return its(val); }
|
||||
void load(string& s) { val = atoi(s.c_str()); }
|
||||
vector<shared_ptr<supersaver>> savers;
|
||||
|
||||
template<class T> struct dsaver : supersaver {
|
||||
T& val;
|
||||
T dft;
|
||||
bool dosave() { return val != dft; }
|
||||
dsaver(T& val) : val(val) { }
|
||||
};
|
||||
|
||||
struct hexsaver : saver {
|
||||
int& val;
|
||||
int dft;
|
||||
void intsaver() { val = dft; }
|
||||
string save() { return itsh(val); }
|
||||
void load(string& s) { val = strtol(s.c_str(), 16); }
|
||||
};
|
||||
template<class T> struct saver : dsaver<T> {};
|
||||
|
||||
struct ldsaver : saver {
|
||||
ld& val;
|
||||
ld dft;
|
||||
void intsaver() { val = dft; }
|
||||
string save() { return ffts(val); }
|
||||
void load(string& s) { val = atof(s.c_str()); }
|
||||
};
|
||||
|
||||
vector<shared_ptr<saver>> savers;
|
||||
|
||||
void initConfig0() {
|
||||
savers.push_back(make_shared<intsaver> ({"cs.charid", cs.charid, 0}));
|
||||
template<class T, class U, class V> void addsaver(T& i, U name, V dft) {
|
||||
auto s = make_shared<saver<T>> (i);
|
||||
s->dft = i = dft;
|
||||
s->name = name;
|
||||
savers.push_back(s);
|
||||
}
|
||||
*/
|
||||
|
||||
template<class T> void addsaver(T& i, string name) {
|
||||
addsaver(i, name, i);
|
||||
}
|
||||
|
||||
template<class T> struct saverenum : supersaver {
|
||||
T& val;
|
||||
T dft;
|
||||
bool dosave() { return val != dft; }
|
||||
saverenum<T>(T& v) : val(v) { }
|
||||
string save() { return its(val); }
|
||||
void load(const string& s) { val = (T) atoi(s.c_str()); }
|
||||
};
|
||||
|
||||
template<class T, class U> void addsaverenum(T& i, U name) {
|
||||
auto s = make_shared<saverenum<T>> (i);
|
||||
s->dft = i;
|
||||
s->name = name;
|
||||
savers.push_back(s);
|
||||
}
|
||||
|
||||
template<> struct saver<int> : dsaver<int> {
|
||||
saver<int>(int& val) : dsaver<int>(val) { }
|
||||
string save() { return its(val); }
|
||||
void load(const string& s) { val = atoi(s.c_str()); }
|
||||
};
|
||||
|
||||
template<> struct saver<char> : dsaver<char> {
|
||||
saver<char>(char& val) : dsaver<char>(val) { }
|
||||
string save() { return its(val); }
|
||||
void load(const string& s) { val = atoi(s.c_str()); }
|
||||
};
|
||||
|
||||
template<> struct saver<bool> : dsaver<bool> {
|
||||
saver<bool>(bool& val) : dsaver<bool>(val) { }
|
||||
string save() { return val ? "yes" : "no"; }
|
||||
void load(const string& s) { val = size(s) && s[0] == 'y'; }
|
||||
};
|
||||
|
||||
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); }
|
||||
};
|
||||
|
||||
template<> struct saver<ld> : dsaver<ld> {
|
||||
saver<ld>(ld& val) : dsaver<ld>(val) { }
|
||||
string save() { return ftssmart(val); }
|
||||
void load(const string& s) { val = atof(s.c_str()); }
|
||||
};
|
||||
|
||||
void addsaver(charstyle& cs, string s) {
|
||||
addsaver(cs.charid, s + ".charid");
|
||||
addsaver(cs.skincolor, s + ".skincolor");
|
||||
addsaver(cs.haircolor, s + ".haircolor");
|
||||
addsaver(cs.dresscolor, s + ".dresscolor");
|
||||
addsaver(cs.swordcolor, s + ".swordcolor");
|
||||
addsaver(cs.dresscolor2, s + ".dresscolor2");
|
||||
addsaver(cs.uicolor, s + ".uicolor");
|
||||
}
|
||||
|
||||
// R:239, G:208, B:207
|
||||
|
||||
unsigned int skincolors[] = { 7, 0xD0D0D0FF, 0xEFD0C9FF, 0xC77A58FF, 0xA58869FF, 0x602010FF, 0xFFDCB1FF, 0xEDE4C8FF };
|
||||
@ -127,69 +175,109 @@ void loadcs(FILE *f, charstyle& cs, int xvernum) {
|
||||
}
|
||||
|
||||
void initConfig() {
|
||||
vid.usingGL = true;
|
||||
vid.antialias = AA_NOGL | AA_FONT | AA_LINES | AA_LINEWIDTH | AA_VERSION;
|
||||
vid.linewidth = 1;
|
||||
vid.flashtime = 8;
|
||||
vid.scale = 1;
|
||||
vid.alpha = 1;
|
||||
vid.sspeed = 0;
|
||||
vid.mspeed = 1;
|
||||
vid.eye = 0;
|
||||
vid.full = false;
|
||||
vid.ballangle = 20;
|
||||
vid.yshift = 0;
|
||||
vid.camera_angle = 0;
|
||||
vid.ballproj = 1;
|
||||
vid.aurastr = 128;
|
||||
vid.aurasmoothen = 5;
|
||||
vid.graphglyph = 1;
|
||||
|
||||
#ifdef ANDROID
|
||||
vid.monmode = 2;
|
||||
vid.wallmode = 3;
|
||||
#else
|
||||
#ifdef PANDORA
|
||||
vid.monmode = 2;
|
||||
vid.wallmode = 3;
|
||||
#else
|
||||
vid.monmode = 4;
|
||||
vid.wallmode = 5;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vid.particles = 1;
|
||||
vid.mobilecompasssize = 30;
|
||||
|
||||
vid.joyvalue = 4800;
|
||||
vid.joyvalue2 = 5600;
|
||||
vid.joypanthreshold = 2500;
|
||||
#ifdef PANDORA
|
||||
vid.joypanspeed = 0.0001;
|
||||
#else
|
||||
vid.joypanspeed = 0;
|
||||
#endif
|
||||
|
||||
vid.framelimit = 75;
|
||||
vid.axes = 1;
|
||||
vid.shifttarget = 2;
|
||||
vid.steamscore = 1;
|
||||
|
||||
initcs(vid.cs);
|
||||
// basic config
|
||||
addsaver(vid.flashtime, "flashtime", 8);
|
||||
addsaver(vid.mobilecompasssize, "mobile compass size", 30);
|
||||
addsaver(vid.axes, "movement help", 1);
|
||||
addsaver(vid.shifttarget, "shift-targetting", 2);
|
||||
addsaver(vid.steamscore, "scores to Steam", 1);
|
||||
initcs(vid.cs); addsaver(vid.cs, "single");
|
||||
addsaver(vid.samegender, "princess choice", false);
|
||||
addsaver(vid.language, "language", -1);
|
||||
addsaver(vid.drawmousecircle, "mouse circle", ISMOBILE || ISPANDORA);
|
||||
addsaver(vid.revcontrol, "reverse control", false);
|
||||
addsaver(musicvolume, "music volume");
|
||||
addsaver(effvolume, "sound effect volume");
|
||||
addsaverenum(glyphsortorder, "glyph sort order");
|
||||
|
||||
// basic graphics
|
||||
|
||||
addsaver(vid.usingGL, "usingGL", true);
|
||||
addsaver(vid.antialias, "antialias", AA_NOGL | AA_FONT | AA_LINES | AA_LINEWIDTH | AA_VERSION);
|
||||
addsaver(vid.linewidth, "linewidth", 1);
|
||||
addsaver(vid.scale, "scale", 1);
|
||||
addsaver(vid.alpha, "projection", 1);
|
||||
addsaver(vid.sspeed, "scrollingspeed", 0);
|
||||
addsaver(vid.mspeed, "movement speed", 1);
|
||||
addsaver(vid.full, "fullscreen", false);
|
||||
addsaver(vid.aurastr, "aura strength", 128);
|
||||
addsaver(vid.aurasmoothen, "aura smoothen", 5);
|
||||
addsaver(vid.graphglyph, "graphical items/kills", 1);
|
||||
addsaver(vid.particles, "extra effects", 1);
|
||||
addsaver(vid.framelimit, "frame limit", 75);
|
||||
addsaver(vid.xres, "xres");
|
||||
addsaver(vid.yres, "yres");
|
||||
addsaver(vid.fsize, "font size");
|
||||
addsaver(vid.darkhepta, "mark heptagons", false);
|
||||
|
||||
// special graphics
|
||||
|
||||
addsaver(vid.eye, "eye distance", 0);
|
||||
addsaver(vid.ballangle, "ball angle", 20);
|
||||
addsaver(vid.yshift, "Y shift", 0);
|
||||
addsaver(vid.camera_angle, "camera angle", 0);
|
||||
addsaver(vid.ballproj, "ballproj", 1);
|
||||
addsaver(vid.monmode, "monster display mode", (ISANDROID || ISPANDORA) ? 2 : 4);
|
||||
addsaver(vid.wallmode, "wall display mode", (ISANDROID || ISPANDORA) ? 3 : 5);
|
||||
|
||||
addsaver(geom3::depth, "3D depth");
|
||||
addsaver(geom3::camera, "3D camera level");
|
||||
addsaver(geom3::wall_height, "3D wall height");
|
||||
addsaver(geom3::rock_wall_ratio, "3D rock-wall ratio");
|
||||
addsaver(geom3::human_wall_ratio, "3D human-wall ratio");
|
||||
addsaver(geom3::lake_top, "3D lake top");
|
||||
addsaver(geom3::lake_bottom, "3D lake bottom");
|
||||
addsaver(geom3::tc_depth, "3D TC depth");
|
||||
addsaver(geom3::tc_camera, "3D TC camera");
|
||||
addsaver(geom3::tc_alpha, "3D TC alpha");
|
||||
addsaver(geom3::highdetail, "3D highdetail");
|
||||
addsaver(geom3::middetail, "3D middetail");
|
||||
|
||||
addsaver(rug::renderonce, "rug-renderonce");
|
||||
addsaver(rug::rendernogl, "rug-rendernogl");
|
||||
addsaver(rug::texturesize, "rug-texturesize");
|
||||
addsaver(rug::scale, "rug-scale");
|
||||
|
||||
addsaverenum(pmodel, "used model");
|
||||
addsaver(polygonal::SI, "polygon sides");
|
||||
addsaver(polygonal::STAR, "polygon star factor");
|
||||
addsaver(polygonal::deg, "polygonal degree");
|
||||
addsaver(conformal::includeHistory, "include history"); // check!
|
||||
addsaver(conformal::lvspeed, "lineview speed");
|
||||
|
||||
addsaver(polygonal::maxcoef, "polynomial degree");
|
||||
for(int i=0; i<polygonal::MSI; i++) {
|
||||
addsaver(polygonal::coefr[i], "polynomial "+its(i)+".real");
|
||||
addsaver(polygonal::coefi[i], "polynomial "+its(i)+".imag");
|
||||
}
|
||||
|
||||
addsaver(conformal::bandhalf, "band width");
|
||||
addsaver(conformal::bandsegment, "band segment");
|
||||
addsaver(conformal::rotation, "conformal rotation");
|
||||
addsaver(conformal::autoband, "automatic band");
|
||||
addsaver(conformal::autobandhistory, "automatic band history");
|
||||
addsaver(conformal::dospiral, "do spiral");
|
||||
|
||||
// control
|
||||
|
||||
addsaver(vid.joyvalue, "vid.joyvalue", 4800);
|
||||
addsaver(vid.joyvalue2, "vid.joyvalue2", 5600);
|
||||
addsaver(vid.joypanthreshold, "vid.joypanthreshold", 2500);
|
||||
addsaver(vid.joypanspeed, "vid.joypanspeed", ISPANDORA ? 0.0001 : 0);
|
||||
addsaver(autojoy, "autojoy");
|
||||
|
||||
vid.killreduction = 0;
|
||||
|
||||
vid.samegender = false;
|
||||
vid.language = -1;
|
||||
|
||||
vid.drawmousecircle = false;
|
||||
vid.revcontrol = false;
|
||||
#ifdef MOBILE
|
||||
vid.drawmousecircle = true;
|
||||
#endif
|
||||
#ifdef PANDORA
|
||||
vid.drawmousecircle = true;
|
||||
#endif
|
||||
// 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);
|
||||
|
||||
shmup::initConfig();
|
||||
}
|
||||
@ -201,36 +289,6 @@ void saveConfig() {
|
||||
addMessage(s0 + "Could not open the config file: " + conffile);
|
||||
return;
|
||||
}
|
||||
fprintf(f, "%d %d %d %d\n", vid.xres, vid.yres, vid.full, vid.fsize);
|
||||
fprintf(f, "%f %f %f %f\n", float(vid.scale), float(vid.eye), float(vid.alpha), float(vid.sspeed));
|
||||
fprintf(f, "%d %d %d %d %d %d %d\n", vid.wallmode, vid.monmode, vid.axes, musicvolume, vid.framelimit, vid.usingGL, vid.antialias);
|
||||
fprintf(f, "%d %d %d %f %d %d\n", vid.joyvalue, vid.joyvalue2, vid.joypanthreshold, float(vid.joypanspeed), autojoy, vid.flashtime);
|
||||
|
||||
savecs(f, vid.cs, 0);
|
||||
|
||||
fprintf(f, "%d %d\n", vid.darkhepta, vid.shifttarget);
|
||||
|
||||
fprintf(f, "%d %d %d %d\n", euclid, euclidland, shmup::on, hardcore);
|
||||
|
||||
shmup::saveConfig(f);
|
||||
|
||||
fprintf(f, "%d %d %d %d %f %d %d\n", rug::renderonce, rug::rendernogl, rug::texturesize, purehepta, rug::scale, vid.steamscore, chaosmode);
|
||||
|
||||
fprintf(f, "%d %d %f %d %d %f\n",
|
||||
pmodel, polygonal::SI, float(polygonal::STAR), polygonal::deg,
|
||||
conformal::includeHistory, float(conformal::lvspeed));
|
||||
|
||||
fprintf(f, "%d %d %d %d %d %d\n",
|
||||
conformal::bandhalf, conformal::bandsegment,
|
||||
conformal::rotation, conformal::autoband, conformal::autobandhistory,
|
||||
conformal::dospiral);
|
||||
|
||||
fprintf(f, "%d", polygonal::maxcoef);
|
||||
for(int i=0; i<=polygonal::maxcoef; i++) fprintf(f, " %lf %lf",
|
||||
(double) real(polygonal::coef[i]), (double) imag(polygonal::coef[i]));
|
||||
|
||||
fprintf(f, "\n%d %d %d %f %d %d\n",
|
||||
vid.revcontrol, vid.drawmousecircle, sightrange, float(vid.mspeed), effvolume, vid.particles);
|
||||
|
||||
{
|
||||
int pt_depth = 0, pt_camera = 0, pt_alpha = 0;
|
||||
@ -241,43 +299,13 @@ void saveConfig() {
|
||||
if(tc_depth < tc_alpha ) pt_alpha ++;
|
||||
if(tc_alpha > tc_camera) pt_alpha++;
|
||||
if(tc_alpha < tc_camera) pt_camera++;
|
||||
|
||||
fprintf(f, "%f %f %f %f %f %f %f %d %d %d %f %f %d\n",
|
||||
float(geom3::depth), float(geom3::camera), float(geom3::wall_height),
|
||||
float(geom3::rock_wall_ratio),
|
||||
float(geom3::human_wall_ratio),
|
||||
float(geom3::lake_top),
|
||||
float(geom3::lake_bottom),
|
||||
pt_depth, pt_camera, pt_alpha,
|
||||
float(geom3::highdetail), float(geom3::middetail),
|
||||
glyphsortorder);
|
||||
|
||||
fprintf(f, "%f %f %f %f\n",
|
||||
float(vid.yshift), float(vid.camera_angle),
|
||||
float(vid.ballangle), float(vid.ballproj)
|
||||
);
|
||||
|
||||
fprintf(f, "%d %d %d %d %f\n", vid.mobilecompasssize, vid.aurastr, vid.aurasmoothen, vid.graphglyph, float(vid.linewidth));
|
||||
tc_alpha = pt_alpha;
|
||||
tc_camera = pt_camera;
|
||||
tc_depth = pt_depth;
|
||||
}
|
||||
|
||||
fprintf(f, "\n\nThis is a configuration file for HyperRogue (version " VER ")\n");
|
||||
fprintf(f, "\n\nThe numbers are:\n");
|
||||
fprintf(f, "screen width & height, fullscreen mode (0=windowed, 1=fullscreen), font size\n");
|
||||
fprintf(f, "scale, eye distance, parameter, scrolling speed\n");
|
||||
fprintf(f, "wallmode, monster mode, cross mode, music volume, framerate limit, usingGL, antialiasing flags\n");
|
||||
fprintf(f, "calibrate first joystick (threshold A, threshold B), calibrate second joystick (pan threshold, pan speed), joy mode\n");
|
||||
fprintf(f, "gender (1=female, 16=same gender prince), language, skin color, hair color, sword color, dress color\n");
|
||||
fprintf(f, "darken hepta, shift target\n");
|
||||
fprintf(f, "euclid, euclid land, shmup, hardcore\n");
|
||||
fprintf(f, "version number, shmup players, alwaysuse, shmup keyboard/joystick config\n");
|
||||
fprintf(f, "hypersian rug config: renderonce, rendernogl, texturesize; purehepta; rug scale; share score; chaosmode\n");
|
||||
fprintf(f, "conformal: model, sides, star, degree, includeHistory, speed\n");
|
||||
fprintf(f, "conformal: bandwidth, segment, rotation, autoband, autohistory, dospiral\n");
|
||||
fprintf(f, "conformal: degree, (degree+1) times {real, imag}\n");
|
||||
fprintf(f, "vid.revcontrol, drawmousecircle, sight range, movement animation speed, sound effect volume, particle effects\n");
|
||||
fprintf(f, "3D parameters, sort order\n");
|
||||
fprintf(f, "yhsift, camera angle, ball angle, ball projection\n");
|
||||
fprintf(f, "compass size, aura strength, aura smoothen factor, graphical glyphs\n");
|
||||
|
||||
for(auto s: savers) if(s->dosave())
|
||||
fprintf(f, "%s=%s\n", s->name.c_str(), s->save().c_str());
|
||||
|
||||
fclose(f);
|
||||
#ifndef MOBILE
|
||||
@ -294,110 +322,150 @@ void readf(FILE *f, ld& x) {
|
||||
x = fl;
|
||||
}
|
||||
|
||||
void loadOldConfig(FILE *f) {
|
||||
int gl=1, aa=1, bb=1, cc, dd, ee;
|
||||
int err;
|
||||
float a, b, c, d;
|
||||
err=fscanf(f, "%f%f%f%f\n", &a, &b, &c, &d);
|
||||
if(err == 4) {
|
||||
vid.scale = a; vid.eye = b; vid.alpha = c; vid.sspeed = d;
|
||||
}
|
||||
err=fscanf(f, "%d%d%d%d%d%d%d", &vid.wallmode, &vid.monmode, &vid.axes, &musicvolume, &vid.framelimit, &gl, &vid.antialias);
|
||||
vid.usingGL = gl;
|
||||
if(vid.antialias == 0) vid.antialias = AA_VERSION | AA_LINES | AA_LINEWIDTH;
|
||||
if(vid.antialias == 1) vid.antialias = AA_NOGL | AA_VERSION | AA_LINES | AA_LINEWIDTH | AA_FONT;
|
||||
double jps = vid.joypanspeed;
|
||||
err=fscanf(f, "%d%d%d%lf%d%d", &vid.joyvalue, &vid.joyvalue2, &vid.joypanthreshold, &jps, &aa, &vid.flashtime);
|
||||
vid.joypanspeed = jps;
|
||||
autojoy = aa; aa = 0;
|
||||
|
||||
loadcs(f, vid.cs, 0);
|
||||
|
||||
aa=0; bb=0;
|
||||
err=fscanf(f, "%d%d", &aa, &bb);
|
||||
vid.darkhepta = aa; vid.shifttarget = bb;
|
||||
|
||||
aa = geometry; bb = euclidland; 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;
|
||||
|
||||
shmup::loadConfig(f);
|
||||
|
||||
aa = rug::renderonce; bb = rug::rendernogl; cc = purehepta; dd = chaosmode; ee = vid.steamscore;
|
||||
double rs = rug::scale;
|
||||
err=fscanf(f, "%d%d%d%d%lf%d%d", &aa, &bb, &rug::texturesize, &cc, &rs, &ee, &dd);
|
||||
rug::renderonce = aa; rug::rendernogl = bb; purehepta = cc; chaosmode = dd; vid.steamscore = ee;
|
||||
rug::scale = rs;
|
||||
|
||||
aa=conformal::includeHistory;
|
||||
double ps = polygonal::STAR, lv = conformal::lvspeed;
|
||||
int pmb = pmodel;
|
||||
err=fscanf(f, "%d%d%lf%d%d%lf",
|
||||
&pmb, &polygonal::SI, &ps, &polygonal::deg,
|
||||
&aa, &lv);
|
||||
pmodel = eModel(pmb);
|
||||
conformal::includeHistory = aa; polygonal::STAR = ps; conformal::lvspeed = lv;
|
||||
|
||||
aa=conformal::autoband; bb=conformal::autobandhistory; cc=conformal::dospiral;
|
||||
err=fscanf(f, "%d%d%d%d%d%d",
|
||||
&conformal::bandhalf, &conformal::bandsegment, &conformal::rotation,
|
||||
&aa, &bb, &cc);
|
||||
conformal::autoband = aa; conformal::autobandhistory = bb; conformal::dospiral = cc;
|
||||
|
||||
err=fscanf(f, "%d", &polygonal::maxcoef);
|
||||
if(polygonal::maxcoef < 0) polygonal::maxcoef = 0;
|
||||
if(polygonal::maxcoef > polygonal::MSI) polygonal::maxcoef = polygonal::MSI;
|
||||
for(int i=0; i<=polygonal::maxcoef; i++) {
|
||||
double re=0, im=0;
|
||||
err=fscanf(f, "%lf%lf", &re, &im);
|
||||
polygonal::coefr[i] = re;
|
||||
polygonal::coefi[i] = im;
|
||||
}
|
||||
|
||||
aa=vid.revcontrol; bb=vid.drawmousecircle;
|
||||
d = vid.mspeed;
|
||||
err=fscanf(f, "%d%d%d%f%d%d", &aa, &bb, &sightrange, &d, &effvolume, &vid.particles);
|
||||
vid.mspeed = d;
|
||||
if(sightrange < 4) sightrange = 4;
|
||||
if(sightrange > 7) sightrange = 7;
|
||||
vid.revcontrol = aa; vid.drawmousecircle = bb;
|
||||
|
||||
readf(f, geom3::depth); readf(f, geom3::camera); readf(f, geom3::wall_height);
|
||||
readf(f, geom3::rock_wall_ratio); readf(f, geom3::human_wall_ratio);
|
||||
readf(f, geom3::lake_top); readf(f, geom3::lake_bottom);
|
||||
|
||||
err=fscanf(f, "%d %d %d", &geom3::tc_depth, &geom3::tc_camera, &geom3::tc_alpha);
|
||||
|
||||
readf(f, geom3::highdetail);
|
||||
geom3::middetail = 200; readf(f, geom3::middetail);
|
||||
if(geom3::middetail == 200) {
|
||||
if(ISMOBILE)
|
||||
geom3::highdetail = 0, geom3::middetail = 3;
|
||||
else
|
||||
geom3::highdetail = geom3::middetail = 5;
|
||||
}
|
||||
|
||||
int gso = glyphsortorder; err=fscanf(f, "%d", &gso); glyphsortorder = eGlyphsortorder(gso);
|
||||
|
||||
readf(f, vid.yshift); readf(f, vid.camera_angle); readf(f, vid.ballangle); readf(f, vid.ballproj);
|
||||
|
||||
jps = vid.linewidth;
|
||||
err=fscanf(f, "%d%d%d%d%lf\n", &vid.mobilecompasssize, &vid.aurastr, &vid.aurasmoothen, &vid.graphglyph, &jps);
|
||||
vid.linewidth = jps;
|
||||
}
|
||||
|
||||
map<string, shared_ptr<supersaver> > allconfigs;
|
||||
|
||||
void parseline(const string& str) {
|
||||
for(int i=0; i<size(str); i++) if(str[i] == '=') {
|
||||
string cname = str.substr(0, i);
|
||||
if(!allconfigs.count(cname)) {
|
||||
printf("Warning: unknown config variable: %s\n", str.c_str());
|
||||
return;
|
||||
}
|
||||
auto sav = allconfigs[cname];
|
||||
sav->load(str.substr(i+1));
|
||||
return;
|
||||
}
|
||||
printf("Warning: config line without equality sign: %s\n", str.c_str());
|
||||
}
|
||||
|
||||
void loadNewConfig(FILE *f) {
|
||||
for(auto& c: savers) allconfigs[c->name] = c;
|
||||
string rd;
|
||||
while(true) {
|
||||
int c = fgetc(f);
|
||||
if(c == -1) break;
|
||||
if(c == 10 || c == 13) {
|
||||
if(rd != "") parseline(rd);
|
||||
rd = "";
|
||||
}
|
||||
else rd += c;
|
||||
}
|
||||
allconfigs.clear();
|
||||
}
|
||||
|
||||
void loadConfig() {
|
||||
|
||||
DEBB(DF_INIT, (debugfile,"load config\n"));
|
||||
DEBB(DF_INIT, (debugfile,"load config\n"));
|
||||
vid.xres = 9999; vid.yres = 9999; vid.framelimit = 300;
|
||||
FILE *f = fopen(conffile, "rt");
|
||||
if(f) {
|
||||
int fs, gl=1, aa=1, bb=1, cc, dd, ee;
|
||||
int err;
|
||||
int fs;
|
||||
err=fscanf(f, "%d%d%d%d", &vid.xres, &vid.yres, &fs, &vid.fsize);
|
||||
vid.full = fs;
|
||||
float a, b, c, d;
|
||||
err=fscanf(f, "%f%f%f%f\n", &a, &b, &c, &d);
|
||||
if(err == 4) {
|
||||
vid.scale = a; vid.eye = b; vid.alpha = c; vid.sspeed = d;
|
||||
if(!err)
|
||||
loadNewConfig(f);
|
||||
else {
|
||||
vid.full = fs;
|
||||
loadOldConfig(f);
|
||||
}
|
||||
err=fscanf(f, "%d%d%d%d%d%d%d", &vid.wallmode, &vid.monmode, &vid.axes, &musicvolume, &vid.framelimit, &gl, &vid.antialias);
|
||||
vid.usingGL = gl;
|
||||
if(vid.antialias == 0) vid.antialias = AA_VERSION | AA_LINES | AA_LINEWIDTH;
|
||||
if(vid.antialias == 1) vid.antialias = AA_NOGL | AA_VERSION | AA_LINES | AA_LINEWIDTH | AA_FONT;
|
||||
double jps = vid.joypanspeed;
|
||||
err=fscanf(f, "%d%d%d%lf%d%d", &vid.joyvalue, &vid.joyvalue2, &vid.joypanthreshold, &jps, &aa, &vid.flashtime);
|
||||
vid.joypanspeed = jps;
|
||||
autojoy = aa; aa = 0;
|
||||
|
||||
loadcs(f, vid.cs, 0);
|
||||
|
||||
aa=0; bb=0;
|
||||
err=fscanf(f, "%d%d", &aa, &bb);
|
||||
vid.darkhepta = aa; vid.shifttarget = bb;
|
||||
|
||||
aa = geometry; bb = euclidland; 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;
|
||||
|
||||
shmup::loadConfig(f);
|
||||
|
||||
aa = rug::renderonce; bb = rug::rendernogl; cc = purehepta; dd = chaosmode; ee = vid.steamscore;
|
||||
double rs = rug::scale;
|
||||
err=fscanf(f, "%d%d%d%d%lf%d%d", &aa, &bb, &rug::texturesize, &cc, &rs, &ee, &dd);
|
||||
rug::renderonce = aa; rug::rendernogl = bb; purehepta = cc; chaosmode = dd; vid.steamscore = ee;
|
||||
rug::scale = rs;
|
||||
|
||||
aa=conformal::includeHistory;
|
||||
double ps = polygonal::STAR, lv = conformal::lvspeed;
|
||||
int pmb = pmodel;
|
||||
err=fscanf(f, "%d%d%lf%d%d%lf",
|
||||
&pmb, &polygonal::SI, &ps, &polygonal::deg,
|
||||
&aa, &lv);
|
||||
pmodel = eModel(pmb);
|
||||
conformal::includeHistory = aa; polygonal::STAR = ps; conformal::lvspeed = lv;
|
||||
|
||||
aa=conformal::autoband; bb=conformal::autobandhistory; cc=conformal::dospiral;
|
||||
err=fscanf(f, "%d%d%d%d%d%d",
|
||||
&conformal::bandhalf, &conformal::bandsegment, &conformal::rotation,
|
||||
&aa, &bb, &cc);
|
||||
conformal::autoband = aa; conformal::autobandhistory = bb; conformal::dospiral = cc;
|
||||
|
||||
err=fscanf(f, "%d", &polygonal::maxcoef);
|
||||
if(polygonal::maxcoef < 0) polygonal::maxcoef = 0;
|
||||
if(polygonal::maxcoef > polygonal::MSI) polygonal::maxcoef = polygonal::MSI;
|
||||
for(int i=0; i<=polygonal::maxcoef; i++) {
|
||||
double re=0, im=0;
|
||||
err=fscanf(f, "%lf%lf", &re, &im);
|
||||
polygonal::coef[i] = cld(re, im);
|
||||
}
|
||||
|
||||
aa=vid.revcontrol; bb=vid.drawmousecircle;
|
||||
d = vid.mspeed;
|
||||
err=fscanf(f, "%d%d%d%f%d%d", &aa, &bb, &sightrange, &d, &effvolume, &vid.particles);
|
||||
vid.mspeed = d;
|
||||
if(sightrange < 4) sightrange = 4;
|
||||
if(sightrange > 7) sightrange = 7;
|
||||
vid.revcontrol = aa; vid.drawmousecircle = bb;
|
||||
|
||||
readf(f, geom3::depth); readf(f, geom3::camera); readf(f, geom3::wall_height);
|
||||
readf(f, geom3::rock_wall_ratio); readf(f, geom3::human_wall_ratio);
|
||||
readf(f, geom3::lake_top); readf(f, geom3::lake_bottom);
|
||||
|
||||
err=fscanf(f, "%d %d %d", &geom3::tc_depth, &geom3::tc_camera, &geom3::tc_alpha);
|
||||
|
||||
readf(f, geom3::highdetail);
|
||||
geom3::middetail = 200; readf(f, geom3::middetail);
|
||||
if(geom3::middetail == 200) {
|
||||
if(ISMOBILE)
|
||||
geom3::highdetail = 0, geom3::middetail = 3;
|
||||
else
|
||||
geom3::highdetail = geom3::middetail = 5;
|
||||
}
|
||||
|
||||
int gso = glyphsortorder; err=fscanf(f, "%d", &gso); glyphsortorder = eGlyphsortorder(gso);
|
||||
|
||||
readf(f, vid.yshift); readf(f, vid.camera_angle); readf(f, vid.ballangle); readf(f, vid.ballproj);
|
||||
|
||||
jps = vid.linewidth;
|
||||
err=fscanf(f, "%d%d%d%d%lf\n", &vid.mobilecompasssize, &vid.aurastr, &vid.aurasmoothen, &vid.graphglyph, &jps);
|
||||
vid.linewidth = jps;
|
||||
|
||||
fclose(f);
|
||||
DEBB(DF_INIT, (debugfile,"Loaded configuration: %s\n", conffile));
|
||||
|
||||
if(err)
|
||||
;
|
||||
}
|
||||
|
||||
polygonal::solve();
|
||||
precalc();
|
||||
}
|
||||
#endif
|
||||
@ -957,7 +1025,7 @@ void show3D() {
|
||||
};
|
||||
}
|
||||
|
||||
void switchcolor(int& c, unsigned int* cs) {
|
||||
void switchcolor(unsigned int& c, unsigned int* cs) {
|
||||
dialog::openColorDialog(c, cs);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
// Hyperbolic Rogue -- the conformal/history mode
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#include <complex>
|
||||
typedef complex<ld> cld;
|
||||
|
||||
namespace polygonal {
|
||||
|
||||
typedef complex<ld> cld;
|
||||
@ -13,10 +16,16 @@ namespace polygonal {
|
||||
ld matrix[MSI][MSI];
|
||||
ld ans[MSI];
|
||||
|
||||
cld coef[MSI];
|
||||
cld coef[MSI];
|
||||
ld coefr[MSI], coefi[MSI];
|
||||
int maxcoef, coefid;
|
||||
|
||||
void solve() {
|
||||
if(pmodel == mdPolynomial) {
|
||||
for(int i=0; i<MSI; i++) coef[i] = cld(coefr[i], coefi[i]);
|
||||
return;
|
||||
}
|
||||
if(pmodel != mdPolygonal) return;
|
||||
if(SI < 3) SI = 3;
|
||||
for(int i=0; i<MSI; i++) ans[i] = cos(M_PI / SI);
|
||||
for(int i=0; i<MSI; i++)
|
||||
@ -547,9 +556,9 @@ namespace conformal {
|
||||
|
||||
if(pmodel == 4) {
|
||||
dialog::addSelItem(XLAT("coefficient"),
|
||||
fts4(real(polygonal::coef[polygonal::coefid])), 'x');
|
||||
fts4(polygonal::coefr[polygonal::coefid]), 'x');
|
||||
dialog::addSelItem(XLAT("coefficient (imaginary)"),
|
||||
fts4(imag(polygonal::coef[polygonal::coefid])), 'y');
|
||||
fts4(polygonal::coefi[polygonal::coefid]), 'y');
|
||||
dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n');
|
||||
}
|
||||
|
||||
@ -583,19 +592,8 @@ namespace conformal {
|
||||
keyhandler = handleKeyC;
|
||||
}
|
||||
|
||||
int ib = 0;
|
||||
ld compbuf;
|
||||
|
||||
void applyIB() {
|
||||
using namespace polygonal;
|
||||
cld& tgt = coef[coefid];
|
||||
if(ib == 1) tgt = cld(compbuf, imag(tgt));
|
||||
if(ib == 2) tgt = cld(real(tgt), compbuf);
|
||||
}
|
||||
|
||||
void handleKeyC(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
ib = 0;
|
||||
|
||||
if(uni == 'e') {
|
||||
if(on) clear();
|
||||
@ -618,7 +616,7 @@ namespace conformal {
|
||||
if(pmodel == mdHalfplane || pmodel == mdBand || pmodel == mdEquidistant || pmodel == mdEquiarea)
|
||||
goto switchagain;
|
||||
}
|
||||
if(pmodel == mdPolygonal) polygonal::solve();
|
||||
polygonal::solve();
|
||||
/* if(pmodel && vid.usingGL) {
|
||||
addMessage(XLAT("openGL mode disabled"));
|
||||
vid.usingGL = false;
|
||||
@ -634,16 +632,12 @@ namespace conformal {
|
||||
else if(sym == 'x' && pmodel == mdPolynomial) {
|
||||
polygonal::maxcoef = max(polygonal::maxcoef, polygonal::coefid);
|
||||
int ci = polygonal::coefid + 1;
|
||||
compbuf = real(polygonal::coef[polygonal::coefid]);
|
||||
dialog::editNumber(compbuf, -10, 10, .01/ci/ci, 0, XLAT("coefficient"), "");
|
||||
ib = 1;
|
||||
dialog::editNumber(polygonal::coefr[polygonal::coefid], -10, 10, .01/ci/ci, 0, XLAT("coefficient"), "");
|
||||
}
|
||||
else if(sym == 'y' && pmodel == mdPolynomial) {
|
||||
polygonal::maxcoef = max(polygonal::maxcoef, polygonal::coefid);
|
||||
int ci = polygonal::coefid + 1;
|
||||
compbuf = imag(polygonal::coef[polygonal::coefid]);
|
||||
dialog::editNumber(compbuf, -10, 10, .01/ci/ci, 0, XLAT("coefficient (imaginary)"), "");
|
||||
ib = 2;
|
||||
dialog::editNumber(polygonal::coefi[polygonal::coefid], -10, 10, .01/ci/ci, 0, XLAT("coefficient (imaginary)"), "");
|
||||
}
|
||||
else if(sym == 'n' && pmodel == mdPolynomial)
|
||||
dialog::editNumber(polygonal::coefid, 0, polygonal::MSI-1, 1, 0, XLAT("which coefficient"), "");
|
||||
|
16
control.cpp
16
control.cpp
@ -526,7 +526,7 @@ void mainloopiter() {
|
||||
drawscreen();
|
||||
}
|
||||
|
||||
if(ev.type == SDL_JOYAXISMOTION) {
|
||||
if(ev.type == SDL_JOYAXISMOTION && normal && DEFAULTCONTROL) {
|
||||
if(ev.jaxis.which == 0) {
|
||||
if(ev.jaxis.axis == 0)
|
||||
joyx = ev.jaxis.value;
|
||||
@ -565,18 +565,30 @@ void mainloopiter() {
|
||||
if(ev.jhat.value == SDL_HAT_RIGHT) dir = 1;
|
||||
if(ev.jhat.value == SDL_HAT_DOWN) dir = 2;
|
||||
if(ev.jhat.value == SDL_HAT_LEFT) dir = 3;
|
||||
printf("%d %d %d\n", joyid, hat, dir);
|
||||
if(joyid < 8 && hat < 4 && dir < 4) {
|
||||
vid.scfg.hataction[joyid][hat][dir] = vid.scfg.setwhat;
|
||||
vid.scfg.setwhat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else if(ev.type == SDL_JOYBUTTONDOWN && DEFAULTCONTROL) {
|
||||
else if(ev.type == SDL_JOYHATMOTION && !normal) {
|
||||
if(ev.jhat.value == SDL_HAT_UP) sym = SDLK_UP;
|
||||
if(ev.jhat.value == SDL_HAT_DOWN) sym = SDLK_DOWN;
|
||||
if(ev.jhat.value == SDL_HAT_LEFT) sym = SDLK_LEFT;
|
||||
if(ev.jhat.value == SDL_HAT_RIGHT) sym = SDLK_RIGHT;
|
||||
}
|
||||
|
||||
else if(ev.type == SDL_JOYBUTTONDOWN && normal && DEFAULTCONTROL) {
|
||||
flashMessages();
|
||||
movepcto(joydir);
|
||||
checkjoy();
|
||||
}
|
||||
|
||||
else if(ev.type == SDL_JOYBUTTONDOWN && !normal) {
|
||||
sym = uni = SDLK_RETURN;
|
||||
}
|
||||
|
||||
if(ev.type == SDL_KEYDOWN) {
|
||||
flashMessages();
|
||||
mousing = false;
|
||||
|
10
dialogs.cpp
10
dialogs.cpp
@ -387,10 +387,10 @@ namespace dialog {
|
||||
|
||||
int colorp = 0;
|
||||
|
||||
int *colorPointer;
|
||||
unsigned int *colorPointer;
|
||||
|
||||
bool handleKeyColor(int sym, int uni) {
|
||||
int& color = *colorPointer;
|
||||
unsigned& color = *colorPointer;
|
||||
|
||||
if(uni >= 'A' && uni <= 'D') {
|
||||
int x = (mousex - vid.xres/4) * 510 / vid.xres;
|
||||
@ -478,7 +478,7 @@ namespace dialog {
|
||||
keyhandler = handleKeyColor;
|
||||
}
|
||||
|
||||
void openColorDialog(int& col, unsigned int *pal) {
|
||||
void openColorDialog(unsigned int& col, unsigned int *pal) {
|
||||
colorPointer = &col; palette = pal;
|
||||
pushScreen(drawColorDialog);
|
||||
}
|
||||
@ -593,7 +593,7 @@ namespace dialog {
|
||||
if(ne.intval == &polygonal::SI) polygonal::solve();
|
||||
if(ne.editwhat == &polygonal::STAR) polygonal::solve();
|
||||
|
||||
conformal::applyIB();
|
||||
polygonal::solve();
|
||||
|
||||
if(ne.editwhat == &geom3::highdetail && geom3::highdetail > geom3::middetail)
|
||||
geom3::middetail = geom3::highdetail;
|
||||
@ -626,7 +626,7 @@ namespace dialog {
|
||||
|
||||
addBreak(100);
|
||||
|
||||
if(cmode && sm::A3) ne.help = explain3D(ne.editwhat);
|
||||
if(cmode & sm::A3) ne.help = explain3D(ne.editwhat);
|
||||
|
||||
if(ne.help != "") {
|
||||
addHelp(ne.help);
|
||||
|
@ -637,6 +637,7 @@ bool highwall(cell *c) {
|
||||
return false;
|
||||
// if(wmspatial && isTree(c)) return false;
|
||||
if(isGrave(c->wall)) return true;
|
||||
if(c->wall == waMirrorWall) return false;
|
||||
return winf[c->wall].glyph == '#' || c->wall == waClosedGate;
|
||||
}
|
||||
|
||||
|
248
game.cpp
248
game.cpp
@ -124,9 +124,9 @@ cellwalker cwt; // single player character position
|
||||
inline cell*& singlepos() { return cwt.c; }
|
||||
inline bool singleused() { return !(shmup::on || multi::players > 1); }
|
||||
|
||||
#include "mtrand.cpp"
|
||||
#include <random>
|
||||
|
||||
MTRand_int32 r;
|
||||
mt19937 r;
|
||||
|
||||
void shrand(int i) {
|
||||
r.seed(i);
|
||||
@ -510,6 +510,9 @@ bool passable(cell *w, cell *from, flagtype flags) {
|
||||
if(w->wall == waMirror || w->wall == waCloud)
|
||||
return F(P_MIRROR | P_AETHER);
|
||||
|
||||
if(w->wall == waMirrorWall)
|
||||
return F(P_MIRRORWALL);
|
||||
|
||||
if(F(P_BULLET)) {
|
||||
if(isFire(w) || w->wall == waBonfireOff || cellHalfvine(w) ||
|
||||
w->wall == waAncientGrave || w->wall == waFreshGrave || w->wall == waRoundTable)
|
||||
@ -632,10 +635,12 @@ bool ghostmove(eMonster m, cell* to, cell* from) {
|
||||
if((m == moWitchGhost || m == moWitchWinter) && to->land != laPower)
|
||||
return false;
|
||||
if(isGhost(m))
|
||||
for(int i=0; i<to->type; i++)
|
||||
for(int i=0; i<to->type; i++) {
|
||||
if(inmirror(to->mov[i])) return false;
|
||||
if(to->mov[i] && to->mov[i] != from && isGhost(to->mov[i]->monst) &&
|
||||
(to->mov[i]->monst == moFriendlyGhost) == (m== moFriendlyGhost))
|
||||
return false;
|
||||
}
|
||||
if(isGhost(m) || m == moWitchGhost) return true;
|
||||
if(m == moGreaterShark) return isWatery(to);
|
||||
if(m == moWitchWinter)
|
||||
@ -1728,6 +1733,10 @@ void killMonster(cell *c, eMonster who, flagtype deathflags) {
|
||||
i->princess = NULL;
|
||||
if(i->bestdist == OUT_OF_PALACE) {
|
||||
items[itSavedPrincess]--;
|
||||
if(items[itSavedPrincess] < 0) {
|
||||
printf("princess below 0\n");
|
||||
items[itSavedPrincess] = 0;
|
||||
}
|
||||
if(items[itSavedPrincess] == 0 && !inv::on) {
|
||||
items[itOrbLove] = 0;
|
||||
princess::reviveAt = gold(NO_LOVE) + 20;
|
||||
@ -5399,6 +5408,11 @@ bool hasSafeOrb(cell *c) {
|
||||
}
|
||||
|
||||
void checkmove() {
|
||||
|
||||
#ifdef INV
|
||||
if(inv::on) inv::compute();
|
||||
#endif
|
||||
|
||||
if(multi::players > 1 && !multi::checkonly) return;
|
||||
if(hardcore) return;
|
||||
msgscroll = 0;
|
||||
@ -5423,6 +5437,20 @@ void checkmove() {
|
||||
canmove = legalmoves[cwt.spin] = true;
|
||||
if(kills[moPlayer]) canmove = false;
|
||||
|
||||
#ifdef INV
|
||||
if(!canmove && !inv::incheck) {
|
||||
if(inv::remaining[itOrbSafety])
|
||||
canmove = true;
|
||||
else {
|
||||
inv::check(1);
|
||||
checkmove();
|
||||
inv::check(-1);
|
||||
}
|
||||
if(canmove)
|
||||
pushScreen(inv::show);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!canmove) {
|
||||
achievement_final(true);
|
||||
if(cmode & sm::NORMAL) showMissionScreen();
|
||||
@ -5435,11 +5463,7 @@ void checkmove() {
|
||||
items[itWarning]-=2;
|
||||
|
||||
for(int i=0; i<ittypes; i++) orbused[i] = orbusedbak[i];
|
||||
if(recallCell && !markOrb(itOrbRecall)) activateRecall();
|
||||
|
||||
#ifdef INV
|
||||
if(inv::on) inv::compute();
|
||||
#endif
|
||||
if(recallCell && !markOrb(itOrbRecall)) activateRecall();
|
||||
}
|
||||
|
||||
// move the PC. Warning: a very long function! todo: refactor
|
||||
@ -5554,7 +5578,7 @@ bool cantGetGrimoire(cell *c2, bool verbose = true) {
|
||||
|
||||
void gainLife() {
|
||||
items[itOrbLife] ++;
|
||||
if(items[itOrbLife] > 5) items[itOrbLife] = 5;
|
||||
if(items[itOrbLife] > 5 && !shmup::on) items[itOrbLife] = 5;
|
||||
}
|
||||
|
||||
void collectMessage(cell *c2, eItem which) {
|
||||
@ -5686,19 +5710,29 @@ bool collectItem(cell *c2, bool telekinesis) {
|
||||
if(isRevivalOrb(c2->item) && multi::revive_queue.size()) {
|
||||
multiRevival(cwt.c, c2);
|
||||
}
|
||||
else if(c2->item == itOrbSpeed) {
|
||||
items[c2->item] += 31;
|
||||
playSound(c2, "pickup-speed");
|
||||
else if(isShmupLifeOrb(c2->item) && shmup::on) {
|
||||
playSound(c2, "pickup-orb"); // TODO summon
|
||||
gainLife();
|
||||
}
|
||||
else if(orbcharges(c2->item)) {
|
||||
eItem it = c2->item;
|
||||
if(it == itOrbRecall) saveRecall(c2);
|
||||
if(it == itOrbFire) playSound(c2, "fire");
|
||||
else if(it == itOrbFire) playSound(c2, "fire");
|
||||
else if(it == itOrbWinter) playSound(c2, "pickup-winter");
|
||||
else if(it == itOrbSpeed) playSound(c2, "pickup-speed");
|
||||
else if(it == itRevolver) playSound(c2, "pickup-key");
|
||||
else playSound(c2, "pickup-orb");
|
||||
if(!items[it]) items[it]++;
|
||||
items[it] += orbcharges(it);
|
||||
}
|
||||
else if(c2->item == itOrbLife) {
|
||||
playSound(c2, "pickup-orb"); // TODO summon
|
||||
if(shmup::on) gainLife();
|
||||
else placeGolem(cwt.c, c2, moGolem);
|
||||
placeGolem(cwt.c, c2, moGolem);
|
||||
}
|
||||
else if(c2->item == itOrbFriend) {
|
||||
playSound(c2, "pickup-orb"); // TODO summon
|
||||
if(shmup::on) gainLife();
|
||||
else placeGolem(cwt.c, c2, moTameBomberbird);
|
||||
placeGolem(cwt.c, c2, moTameBomberbird);
|
||||
}
|
||||
#ifdef TOUR
|
||||
else if(tour::on && (c2->item == itOrbSafety || c2->item == itOrbRecall)) {
|
||||
@ -5715,145 +5749,6 @@ bool collectItem(cell *c2, bool telekinesis) {
|
||||
activateSafety(c2->land);
|
||||
return true;
|
||||
}
|
||||
else if(c2->item == itOrbLightning) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbStone) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 61;
|
||||
}
|
||||
else if(c2->item == itOrbNature) {
|
||||
playSound(c2, "pickup-orb");
|
||||
if(shmup::on) gainLife();
|
||||
else items[c2->item] += 61;
|
||||
}
|
||||
else if(c2->item == itOrbRecall) {
|
||||
saveRecall(c2);
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 61;
|
||||
}
|
||||
else if(c2->item == itOrbTime) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbLove) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itOrbSpace) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbThorns) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbSword) {
|
||||
playSound(c2, "pickup-orb");
|
||||
if(!items[itOrbSword] && !items[itOrbSword2])
|
||||
sword::shuffle();
|
||||
items[c2->item] += 61 + 30 * multi::activePlayers();
|
||||
}
|
||||
else if(c2->item == itOrbSword2) {
|
||||
playSound(c2, "pickup-orb");
|
||||
if(!items[itOrbSword] && !items[itOrbSword2])
|
||||
sword::shuffle();
|
||||
items[c2->item] += 41 + 20 * multi::activePlayers();
|
||||
}
|
||||
else if(c2->item == itOrbFlash) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbShield) {
|
||||
playSound(c2, "pickup-orb"); // TODO Shield
|
||||
items[c2->item] += 16;
|
||||
orbused[itOrbShield] = false;
|
||||
}
|
||||
else if(c2->item == itOrbWater) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itOrbAir) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 67;
|
||||
}
|
||||
else if(c2->item == itOrbFrog) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 45;
|
||||
}
|
||||
else if(c2->item == itOrbDash) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 45;
|
||||
}
|
||||
else if(c2->item == itOrbDiscord) {
|
||||
playSound(c2, "pickup-orb");
|
||||
// make it seem to be 23
|
||||
if(!items[c2->item]) items[c2->item]++;
|
||||
items[c2->item] += 23;
|
||||
}
|
||||
else if(c2->item == itOrbSummon) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 121;
|
||||
}
|
||||
else if(c2->item == itOrbMatter) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 67;
|
||||
}
|
||||
else if(c2->item == itOrbHorns) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 67;
|
||||
}
|
||||
else if(c2->item == itOrbBull) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 67;
|
||||
}
|
||||
else if(c2->item == itOrbFish) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 21 + 10 * multi::activePlayers();
|
||||
}
|
||||
else if(c2->item == itOrbWinter) {
|
||||
playSound(c2, "pickup-winter");
|
||||
items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itRevolver) {
|
||||
playSound(c2, "pickup-key");
|
||||
items[c2->item] = 6;
|
||||
}
|
||||
else if(c2->item == itOrbStunning) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 61;
|
||||
}
|
||||
else if(c2->item == itOrbLuck) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 61;
|
||||
}
|
||||
else if(c2->item == itOrbUndeath) {
|
||||
playSound(c2, "pickup-orb");
|
||||
if(shmup::on) gainLife();
|
||||
else items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itOrbFreedom) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itOrb37) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 51;
|
||||
}
|
||||
else if(c2->item == itOrbEnergy) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 51;
|
||||
}
|
||||
else if(c2->item == itOrbDomination) {
|
||||
playSound(c2, "pickup-orb");
|
||||
if(shmup::on) gainLife();
|
||||
else items[c2->item] += 91;
|
||||
}
|
||||
else if(c2->item == itOrbShell) {
|
||||
playSound(c2, "pickup-orb"); // TOOD shield
|
||||
items[c2->item] += 67;
|
||||
}
|
||||
else if(c2->item == itBabyTortoise) {
|
||||
using namespace tortoise;
|
||||
int bnew = babymap[c2];
|
||||
@ -5869,47 +5764,6 @@ bool collectItem(cell *c2, bool telekinesis) {
|
||||
}
|
||||
else items[itBabyTortoise]++;
|
||||
}
|
||||
else if(c2->item == itOrbBeauty) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 41;
|
||||
}
|
||||
else if(c2->item == itOrbEmpathy) {
|
||||
playSound(c2, "pickup-orb");
|
||||
if(shmup::on) gainLife();
|
||||
else items[c2->item] += 41;
|
||||
}
|
||||
else if(c2->item == itOrbFire) {
|
||||
playSound(c2, "fire");
|
||||
items[c2->item] += (sphere ? 3 : 31);
|
||||
}
|
||||
else if(c2->item == itOrbDragon) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += sphere ? 10 : 78;
|
||||
}
|
||||
else if(c2->item == itOrbIllusion) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbPsi) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbInvis) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itOrbAether) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 31;
|
||||
}
|
||||
else if(c2->item == itOrbDigging) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbTeleport) {
|
||||
playSound(c2, "pickup-orb");
|
||||
items[c2->item] += 78;
|
||||
}
|
||||
else if(c2->item == itOrbYendor && peace::on) {
|
||||
if(!items[itDodeca]) {
|
||||
addMessage(XLAT("Collect as many Dodecahedra as you can, then return here!"));
|
||||
@ -7003,6 +6857,8 @@ bool movepcto(int d, int subdir, bool checkonly) {
|
||||
|
||||
if(multi::players == 1) monstersTurn();
|
||||
|
||||
check_total_victory();
|
||||
|
||||
if(items[itWhirlpool] && cwt.c->land != laWhirlpool && !whirlpool::escaped) {
|
||||
whirlpool::escaped = true;
|
||||
achievement_gain("WHIRL1");
|
||||
|
122
graph.cpp
122
graph.cpp
@ -4,6 +4,8 @@
|
||||
|
||||
// basic graphics:
|
||||
|
||||
int inmirrorcount = 0;
|
||||
|
||||
bool wmspatial, wmescher, wmplain, wmblack, wmascii;
|
||||
bool mmspatial, mmhigh, mmmon, mmitem;
|
||||
int maxreclevel, reclevel;
|
||||
@ -614,6 +616,7 @@ bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks,
|
||||
if(it == itOrbUndeath) icol = minf[moFriendlyGhost].color;
|
||||
if(it == itOrbRecall) icol = 0x101010;
|
||||
hpcshape& sh =
|
||||
it == itOrbLove ? shLoveRing :
|
||||
isRangedOrb(it) ? shTargetRing :
|
||||
isOffensiveOrb(it) ? shSawRing :
|
||||
isFriendOrb(it) ? shPeaceRing :
|
||||
@ -1023,9 +1026,12 @@ bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, dou
|
||||
queuepoly(VBIRD * Mirror, shGadflyEye, darkena(col, 2, 0xFF));
|
||||
}
|
||||
else if(m == moVampire || m == moBat) {
|
||||
if(m == moBat) ShadowV(V, shBatWings); // but vampires have no shadow
|
||||
queuepoly(VBIRD, shBatWings, darkena(0x303030, 0, 0xFF));
|
||||
queuepoly(VBIRD, shBatBody, darkena(0x606060, 0, 0xFF));
|
||||
// vampires have no shadow and no mirror images
|
||||
if(m == moBat) ShadowV(V, shBatWings);
|
||||
if(m == moBat || !inmirrorcount) {
|
||||
queuepoly(VBIRD, shBatWings, darkena(0x303030, 0, 0xFF));
|
||||
queuepoly(VBIRD, shBatBody, darkena(0x606060, 0, 0xFF));
|
||||
}
|
||||
/* queuepoly(V, shBatMouth, darkena(0xC00000, 0, 0xFF));
|
||||
queuepoly(V, shBatFang, darkena(0xFFC0C0, 0, 0xFF));
|
||||
queuepoly(V*Mirror, shBatFang, darkena(0xFFC0C0, 0, 0xFF));
|
||||
@ -1444,7 +1450,7 @@ bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) {
|
||||
}
|
||||
|
||||
double chainAngle(cell *c, transmatrix& V, cell *c2, double dft) {
|
||||
if(!gmatrix0.count(c2)) return dft;
|
||||
if(inmirrorcount || !gmatrix0.count(c2)) return dft;
|
||||
hyperpoint h = C0;
|
||||
if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h;
|
||||
h = inverse(V) * gmatrix0[c2] * h;
|
||||
@ -1453,7 +1459,7 @@ double chainAngle(cell *c, transmatrix& V, cell *c2, double dft) {
|
||||
|
||||
// equivalent to V = V * spin(-chainAngle(c,V,c2,dft));
|
||||
bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, int b) {
|
||||
if(!gmatrix0.count(c2)) {
|
||||
if(inmirrorcount || !gmatrix0.count(c2)) {
|
||||
V = V * ddspin(c,i,b);
|
||||
return false;
|
||||
}
|
||||
@ -1502,7 +1508,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
||||
double footphaseb = 0, footphase = 0;
|
||||
|
||||
transmatrix Vs = Vparam; nospins = applyAnimation(c, Vs, footphase, LAYER_SMALL);
|
||||
transmatrix Vb = Vparam; nospinb = applyAnimation(c, Vb, footphaseb, LAYER_BIG);
|
||||
transmatrix Vb = Vparam;
|
||||
if(!inmirrorcount) nospinb = applyAnimation(c, Vb, footphaseb, LAYER_BIG);
|
||||
// nospin = true;
|
||||
|
||||
eMonster m = c->monst;
|
||||
@ -1638,6 +1645,8 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, int col) {
|
||||
|
||||
if(!nospins)
|
||||
Vs = Vs * ddspin(c, c->mondir, flipplayer ? S42 : 0);
|
||||
|
||||
if(inmirrorcount&1) col ^= minf[moMirror].color ^ minf[moMirage].color;
|
||||
|
||||
if(c->monst == moMirror) Vs = Vs * Mirror;
|
||||
|
||||
@ -2240,7 +2249,8 @@ void setcolors(cell *c, int& wcol, int &fcol) {
|
||||
if(c->wall == waPlatform) wcol = 0xF0F0A0;
|
||||
}
|
||||
if(c->land == laWineyard) fcol = 0x006000;
|
||||
if(c->land == laMirror) fcol = 0x808080;
|
||||
if(c->land == laMirror || c->land == laMirrorWall)
|
||||
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);
|
||||
@ -2509,7 +2519,7 @@ 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))
|
||||
if(c->land == laMinefield && c->wall == waMineMine && ((cmode & sm::MAP) || !canmove))
|
||||
fcol = wcol = 0xFF4040;
|
||||
|
||||
if(mightBeMine(c) && mineMarkedSafe(c))
|
||||
@ -2792,14 +2802,17 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
qfi.shape = NULL; qfi.special = false;
|
||||
ivoryz = isGravityLand(c->land);
|
||||
|
||||
transmatrix& gm = gmatrix[c];
|
||||
bool orig =
|
||||
gm[2][2] == 0 ? true :
|
||||
torus ? hypot(gm[0][2], gm[1][2]) >= hypot(V[0][2], V[1][2]) :
|
||||
(sphere && vid.alphax >= 1.001) ? fabs(gm[2][2]-1) <= fabs(V[2][2]-1) :
|
||||
fabs(gm[2][2]-1) >= fabs(V[2][2]-1) - 1e-8;
|
||||
bool orig = false;
|
||||
if(!inmirrorcount) {
|
||||
transmatrix& gm = gmatrix[c];
|
||||
orig =
|
||||
gm[2][2] == 0 ? true :
|
||||
torus ? hypot(gm[0][2], gm[1][2]) >= hypot(V[0][2], V[1][2]) :
|
||||
(sphere && vid.alphax >= 1.001) ? fabs(gm[2][2]-1) <= fabs(V[2][2]-1) :
|
||||
fabs(gm[2][2]-1) >= fabs(V[2][2]-1) - 1e-8;
|
||||
|
||||
if(orig) gm = V;
|
||||
if(orig) gm = V;
|
||||
}
|
||||
|
||||
if(behindsphere(V)) return;
|
||||
|
||||
@ -2862,7 +2875,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
|
||||
hyperpoint VC0 = tC0(V);
|
||||
|
||||
if(intval(mouseh, VC0) < modist) {
|
||||
if(inmirrorcount) ;
|
||||
else if(intval(mouseh, VC0) < modist) {
|
||||
modist2 = modist; mouseover2 = mouseover;
|
||||
modist = intval(mouseh, VC0);
|
||||
mouseover = c;
|
||||
@ -2871,7 +2885,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
modist2 = intval(mouseh, VC0);
|
||||
mouseover2 = c;
|
||||
}
|
||||
|
||||
|
||||
if(!torus) {
|
||||
double dfc = euclid ? intval(VC0, C0) : VC0[2];
|
||||
|
||||
@ -2892,6 +2906,19 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
}
|
||||
}
|
||||
|
||||
if(inmirror(c)) {
|
||||
if(inmirrorcount >= 10) return;
|
||||
cellwalker cw(c, 0, mirrored);
|
||||
cw = mirror::reflect(cw);
|
||||
int cmc = (cw.mirrored == mirrored) ? 2 : 1;
|
||||
inmirrorcount += cmc;
|
||||
if(cw.mirrored != mirrored) V = V * Mirror;
|
||||
if(cw.spin) V = V * spin(2*M_PI*cw.spin/cw.c->type);
|
||||
drawcell(cw.c, V, 0, cw.mirrored);
|
||||
inmirrorcount -= cmc;
|
||||
return;
|
||||
}
|
||||
|
||||
// int col = 0xFFFFFF - 0x20 * c->maxdist - 0x2000 * c->cpdist;
|
||||
|
||||
if(!buggyGeneration && c->mpdist > 8 && !cheater) return; // not yet generated
|
||||
@ -2904,8 +2931,20 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
int wcol, fcol, asciicol;
|
||||
|
||||
setcolors(c, wcol, fcol);
|
||||
|
||||
if(inmirror(c)) {
|
||||
// for debugging
|
||||
if(c->land == laMirrored) fcol = 0x008000;
|
||||
if(c->land == laMirrorWall2) fcol = 0x800000;
|
||||
if(c->land == laMirrored2) fcol = 0x000080;
|
||||
}
|
||||
|
||||
for(int k=0; k<inmirrorcount; k++)
|
||||
wcol = gradient(wcol, 0xC0C0FF, 0, 0.2, 1),
|
||||
fcol = gradient(fcol, 0xC0C0FF, 0, 0.2, 1);
|
||||
|
||||
// addaura(tC0(V), wcol);
|
||||
int zcol = fcol;
|
||||
int zcol = fcol;
|
||||
|
||||
if(peace::on && peace::hint && c->land != laTortoise) {
|
||||
int d =
|
||||
@ -2918,6 +2957,11 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
fcol = gradient(fcol, dc, 0, .3, 1);
|
||||
}
|
||||
|
||||
if(c->land == laMirrored || c->land == laMirrorWall2 || c->land == laMirrored2) {
|
||||
string label = its(c->landparam);
|
||||
queuestr(V, 1 * .2, label, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
if(viewdists) {
|
||||
int cd = celldistance(c, cwt.c);
|
||||
string label = its(cd);
|
||||
@ -3113,6 +3157,44 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
}
|
||||
#endif
|
||||
|
||||
else if(c->land == laMirrorWall) {
|
||||
int d = mirror::mirrordir(c);
|
||||
bool onleft = c->type == 7;
|
||||
if(c->type == 7 && c->barleft == laMirror)
|
||||
onleft = !onleft;
|
||||
if(c->type == 6 && c->mov[d]->barleft == laMirror)
|
||||
onleft = !onleft;
|
||||
if(purehepta) onleft = !onleft;
|
||||
|
||||
if(d == -1) {
|
||||
for(d=0; d<6; d++)
|
||||
if(c->mov[d] && c->mov[(1+d)%6] && c->mov[d]->land == laMirrorWall && c->mov[(1+d)%6]->land == laMirrorWall)
|
||||
break;
|
||||
qfi.spin = ddspin(c, d, 0);
|
||||
transmatrix V2 = V * qfi.spin;
|
||||
for(int d=0; d<6; d++) {
|
||||
inmirrorcount+=d;
|
||||
qfloor(c, V2 * spin(d*M_PI/3), shHalfFloor[2], darkena(fcol, fd, 0xFF));
|
||||
inmirrorcount-=d;
|
||||
}
|
||||
const int layers = 2 << detaillevel;
|
||||
for(int z=1; z<layers; z++)
|
||||
queuepolyat(mscale(V2, zgrad0(0, geom3::wall_height, z, layers)), shHalfMirror[2], 0xC0C0C080, PPR_WALL3+z-layers);
|
||||
}
|
||||
else {
|
||||
qfi.spin = ddspin(c, d, S42);
|
||||
transmatrix V2 = V * qfi.spin;
|
||||
inmirrorcount++;
|
||||
qfloor(c, mirrorif(V2, !onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF));
|
||||
inmirrorcount--;
|
||||
qfloor(c, mirrorif(V2, onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF));
|
||||
|
||||
const int layers = 2 << detaillevel;
|
||||
for(int z=1; z<layers; z++)
|
||||
queuepolyat(mscale(V2, zgrad0(0, geom3::wall_height, z, layers)), shHalfMirror[ct6], 0xC0C0C080, PPR_WALL3+z-layers);
|
||||
}
|
||||
}
|
||||
|
||||
else if(c->land == laWineyard && cellHalfvine(c)) {
|
||||
|
||||
int i =-1;
|
||||
@ -3606,6 +3688,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
}
|
||||
}
|
||||
|
||||
else if(c->wall == waMirrorWall) ;
|
||||
|
||||
else if(highwall(c)) {
|
||||
zcol = wcol;
|
||||
int wcol0 = wcol;
|
||||
@ -4363,6 +4447,7 @@ void drawthemap() {
|
||||
maxreclevel,
|
||||
hsOrigin, ypush(vid.yshift) * sphereflip * View);
|
||||
}
|
||||
ivoryz = false;
|
||||
|
||||
linepatterns::drawAll();
|
||||
|
||||
@ -4589,6 +4674,7 @@ void drawfullmap() {
|
||||
}
|
||||
#endif
|
||||
profile_start(2);
|
||||
|
||||
drawaura();
|
||||
drawqueue();
|
||||
profile_stop(2);
|
||||
|
84
help.cpp
84
help.cpp
@ -36,6 +36,15 @@ string buildHelpText() {
|
||||
"automatically cancels all moves which result in that.\n\n"
|
||||
);
|
||||
|
||||
if(inv::on)
|
||||
h += XLAT(
|
||||
"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"
|
||||
);
|
||||
else
|
||||
h += XLAT(
|
||||
"There are many lands in HyperRogue. Collect 10 treasure "
|
||||
"in the given land type to complete it; this enables you to "
|
||||
@ -127,6 +136,7 @@ string helptitle(string s, int col) {
|
||||
}
|
||||
|
||||
string princessReviveHelp() {
|
||||
if(inv::on) return "";
|
||||
string h = "\n\n" +
|
||||
XLAT("Killed %1 can be revived with Orb of the Love, after you collect 20 more $$$.", moPrincess);
|
||||
if(princess::reviveAt)
|
||||
@ -136,7 +146,8 @@ string princessReviveHelp() {
|
||||
}
|
||||
|
||||
void describeOrb(string& help, const orbinfo& oi) {
|
||||
eOrbLandRelation olr = getOLR(oi.orb, cwt.c->land);
|
||||
if(inv::on) return;
|
||||
eOrbLandRelation olr = getOLR(oi.orb, getPrizeLand());
|
||||
eItem tr = treasureType(oi.l);
|
||||
help += "\n\n" + XLAT(olrDescriptions[olr], cwt.c->land, tr, treasureType(cwt.c->land));
|
||||
int t = items[tr] * landMultiplier(oi.l);
|
||||
@ -222,6 +233,51 @@ string generateHelpForItem(eItem it) {
|
||||
}
|
||||
}
|
||||
|
||||
if(inv::on) {
|
||||
if(it == itOrbYendor || it == itHell) {
|
||||
help += XLAT(
|
||||
"\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.");
|
||||
}
|
||||
|
||||
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(
|
||||
"\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."
|
||||
);
|
||||
}
|
||||
|
||||
if(it == itOrbYendor || it == itHolyGrail)
|
||||
help += XLAT(
|
||||
"\n\nCollect %the1 to gain an extra Orb of the Mirror. "
|
||||
"You can gain further Orbs of the Mirror by collecting 2, 4, 8..."
|
||||
);
|
||||
|
||||
if(it == itOrbLuck)
|
||||
help += XLAT(
|
||||
"\n\nIn the Orb Strategy Mode, the Orb of Luck also "
|
||||
"significantly increases the frequency of Great Walls, Crossroads IV, "
|
||||
"and sub-lands."
|
||||
);
|
||||
|
||||
if(it == itBone)
|
||||
help += XLAT(
|
||||
"\n\nIn the Orb Strategy Mode, each 25 Necromancer's Totems "
|
||||
"you are given a random offensive Orb."
|
||||
);
|
||||
}
|
||||
|
||||
if(itemclass(it) == IC_ORB || it == itGreenStone || it == itOrbYendor) {
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
@ -237,7 +293,7 @@ string generateHelpForItem(eItem it) {
|
||||
help += XLAT("\n\nOrb unlocked: %1", oi.orb);
|
||||
describeOrb(help, oi);
|
||||
}
|
||||
else if(oi.l == cwt.c->land) {
|
||||
else if(oi.l == cwt.c->land || inv::on) {
|
||||
help += XLAT("\n\nSecondary orb: %1", oi.orb);
|
||||
describeOrb(help, oi);
|
||||
}
|
||||
@ -537,7 +593,7 @@ void describeMouseover() {
|
||||
else if(c->wall != waInvisibleFloor) {
|
||||
out = XLAT1(linf[c->land].name);
|
||||
help = generateHelpForLand(c->land);
|
||||
|
||||
|
||||
if(c->land == laIce || c->land == laCocytus)
|
||||
out += " (" + fts(heat::celsius(c)) + " °C)";
|
||||
if(c->land == laDryForest && c->landparam)
|
||||
@ -561,27 +617,7 @@ void describeMouseover() {
|
||||
if(c->land == laTortoise && tortoise::seek()) out += " " + tortoise::measure(getBits(c));
|
||||
|
||||
if(buggyGeneration) {
|
||||
char buf[20]; sprintf(buf, " H=%d M=%d", c->landparam, c->mpdist); out += buf;
|
||||
}
|
||||
|
||||
if(false) {
|
||||
|
||||
out += " LP:" + itsh(c->landparam)+"/"+its(turncount);
|
||||
|
||||
out += " CD:" + its(celldist(c));
|
||||
|
||||
out += " D:" + its(c->mpdist);
|
||||
|
||||
char zz[64]; sprintf(zz, " P%p", c); out += zz;
|
||||
|
||||
if(euclid) {
|
||||
for(int i=0; i<4; i++) out += " " + its(getEuclidCdata(c->master)->val[i]);
|
||||
out += " " + itsh(getBits(c));
|
||||
}
|
||||
else {
|
||||
for(int i=0; i<4; i++) out += " " + its(getHeptagonCdata(c->master)->val[i]);
|
||||
out += " " + fts(tortoise::getScent(getBits(c)));
|
||||
}
|
||||
char buf[80]; sprintf(buf, " %p H=%d M=%d", c, c->landparam, c->mpdist); out += buf;
|
||||
}
|
||||
|
||||
if(randomPatternsMode)
|
||||
|
@ -209,6 +209,14 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
|
||||
else if(argis("-fix")) {
|
||||
fixseed = true; autocheat = true;
|
||||
}
|
||||
else if(argis("-fixx")) {
|
||||
fixseed = true; autocheat = true;
|
||||
shift(); startseed = argi();
|
||||
}
|
||||
else if(argis("-steplimit")) {
|
||||
fixseed = true; autocheat = true;
|
||||
shift(); steplimit = argi();
|
||||
}
|
||||
else if(argis("-qpar")) {
|
||||
int p;
|
||||
shift(); sscanf(args(), "%d,%d,%d",
|
||||
|
65
hyper.h
65
hyper.h
@ -7,7 +7,7 @@
|
||||
|
||||
#define LB_YENDOR_CHALLENGE 40
|
||||
#define LB_PURE_TACTICS 41
|
||||
#define NUMLEADER 69
|
||||
#define NUMLEADER 70
|
||||
#define LB_PURE_TACTICS_SHMUP 49
|
||||
#define LB_PURE_TACTICS_COOP 50
|
||||
|
||||
@ -73,6 +73,7 @@ eItem treasureType(eLand l);
|
||||
void buildBarrier(cell *c, int d, eLand l = laNone);
|
||||
void extendBarrier(cell *c);
|
||||
bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr);
|
||||
bool buildBarrier6(struct cellwalker cw, int type);
|
||||
bool makeEmpty(cell *c);
|
||||
bool isCrossroads(eLand l);
|
||||
enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMultiGo };
|
||||
@ -134,7 +135,8 @@ void activateActiv(cell *c, bool msg);
|
||||
// shmup
|
||||
|
||||
struct charstyle {
|
||||
int charid, skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor;
|
||||
int charid;
|
||||
unsigned skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor;
|
||||
};
|
||||
|
||||
string csname(charstyle& cs);
|
||||
@ -271,7 +273,7 @@ void drawfullmap();
|
||||
bool displaystr(int x, int y, int shift, int size, const char *str, int color, int align);
|
||||
bool displaystr(int x, int y, int shift, int size, const string& str, int color, int align);
|
||||
|
||||
extern int darken;
|
||||
extern int darken, inmirrorcount;
|
||||
void calcparam();
|
||||
|
||||
#ifdef USE_SDL
|
||||
@ -395,7 +397,7 @@ namespace rug {
|
||||
extern bool renderonce;
|
||||
extern bool rendernogl;
|
||||
extern int texturesize;
|
||||
extern double scale;
|
||||
extern ld scale;
|
||||
void show();
|
||||
void init();
|
||||
void close();
|
||||
@ -406,8 +408,6 @@ namespace rug {
|
||||
#endif
|
||||
|
||||
#define HASLINEVIEW
|
||||
#include <complex>
|
||||
typedef complex<ld> cld;
|
||||
|
||||
namespace conformal {
|
||||
extern bool on;
|
||||
@ -440,7 +440,7 @@ namespace polygonal {
|
||||
extern int SI;
|
||||
extern ld STAR;
|
||||
extern int deg;
|
||||
extern complex<ld> coef[MSI];
|
||||
extern ld coefr[MSI], coefi[MSI];
|
||||
extern int maxcoef, coefid;
|
||||
void solve();
|
||||
pair<ld, ld> compute(ld x, ld y);
|
||||
@ -469,6 +469,7 @@ extern bool localKill(shmup::monster *m);
|
||||
#define P_ONPLAYER (1<<6) // always can step on the player
|
||||
#define P_FLYING (1<<7) // is flying
|
||||
#define P_BULLET (1<<8) // bullet can fly through more things
|
||||
#define P_MIRRORWALL (1<<9) // mirror images go through mirror walls
|
||||
#define P_JUMP1 (1<<10) // first part of a jump
|
||||
#define P_JUMP2 (1<<11) // second part of a jump
|
||||
#define P_TELE (1<<12) // teleport onto
|
||||
@ -519,7 +520,7 @@ extern bool safety;
|
||||
|
||||
#define SAGEMELT .1
|
||||
#define TEMPLE_EACH 6
|
||||
#define PT(x, y) ((tactic::on || quotient == 2) ? (y) : (x))
|
||||
#define PT(x, y) ((tactic::on || quotient == 2) ? (y) : inv::on ? min(2*(y),x) : (x))
|
||||
#define ROCKSNAKELENGTH 50
|
||||
#define WORMLENGTH 15
|
||||
#define PUREHARDCORE_LEVEL 10
|
||||
@ -540,7 +541,7 @@ bool isAlchAny(eWall w);
|
||||
bool isAlchAny(cell *c);
|
||||
|
||||
#define YDIST 101
|
||||
#define MODECODES 254
|
||||
#define MODECODES 255
|
||||
|
||||
extern cellwalker cwt; // player character position
|
||||
extern int sval;
|
||||
@ -827,7 +828,7 @@ namespace dialog {
|
||||
void addSelItem(string body, string value, int key);
|
||||
void addBoolItem(string body, bool value, int key);
|
||||
void addColorItem(string body, int value, int key);
|
||||
void openColorDialog(int& col, unsigned int *pal = palette);
|
||||
void openColorDialog(unsigned int& col, unsigned int *pal = palette);
|
||||
void addHelp(string body);
|
||||
void addInfo(string body, int color = 0xC0C0C0);
|
||||
void addItem(string body, int key);
|
||||
@ -1304,8 +1305,14 @@ bool createOnSea(eLand old);
|
||||
|
||||
namespace inv {
|
||||
extern bool on;
|
||||
extern bool usedForbidden;
|
||||
extern int remaining[ittypes];
|
||||
void compute();
|
||||
void applyBox(eItem it);
|
||||
|
||||
extern int incheck;
|
||||
void check(int delta);
|
||||
void show();
|
||||
}
|
||||
|
||||
bool drawItemType(eItem it, cell *c, const transmatrix& V, int icol, int ticks, bool hidden);
|
||||
@ -1327,6 +1334,9 @@ typedef hookset<void()> *purehookset;
|
||||
|
||||
template<class T, class U> int addHook(hookset<T>*& m, int prio, const U& hook) {
|
||||
if(!m) m = new hookset<T> ();
|
||||
while(m->count(prio)) {
|
||||
prio++;
|
||||
}
|
||||
(*m)[prio] = hook;
|
||||
return 0;
|
||||
}
|
||||
@ -1469,3 +1479,38 @@ namespace leader { void showMenu(); void handleKey(int sym, int uni); }
|
||||
bool needConfirmation();
|
||||
|
||||
extern const char* geometrynames_short[gGUARD];
|
||||
|
||||
namespace mirror {
|
||||
cellwalker reflect(cellwalker cw, bool debug = false);
|
||||
}
|
||||
|
||||
bool inmirror(eLand l);
|
||||
bool inmirror(cell *c);
|
||||
bool inmirror(const cellwalker& cw);
|
||||
|
||||
void queuemarkerat(const transmatrix& V, int col);
|
||||
|
||||
void check_total_victory();
|
||||
void applyBoxNum(int& i, string name = "");
|
||||
extern int hinttoshow;
|
||||
|
||||
bool isShmupLifeOrb(eItem it);
|
||||
int orbcharges(eItem it);
|
||||
|
||||
#ifdef PANDORA
|
||||
static const bool ISPANDORA = true;
|
||||
#else
|
||||
static const bool ISPANDORA = false;
|
||||
#endif
|
||||
|
||||
int gradient(int c0, int c1, ld v0, ld v, ld v1);
|
||||
|
||||
struct hint {
|
||||
time_t last;
|
||||
function<bool()> usable;
|
||||
function<void()> display;
|
||||
function<void()> action;
|
||||
};
|
||||
|
||||
extern hint hints[];
|
||||
int counthints();
|
||||
|
8
hyper.rc
8
hyper.rc
@ -1,8 +1,8 @@
|
||||
id ICON "hr-icon.ico"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 9,4,0,15
|
||||
PRODUCTVERSION 9,4,0,15
|
||||
FILEVERSION 9,4,0,13
|
||||
PRODUCTVERSION 9,4,0,13
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
@ -10,12 +10,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Zeno Rogue"
|
||||
VALUE "FileDescription", "A roguelike in non-euclidean space"
|
||||
VALUE "FileVersion", "94n1"
|
||||
VALUE "FileVersion", "A10.0"
|
||||
VALUE "InternalName", "hyper"
|
||||
VALUE "LegalCopyright", "Zeno Rogue"
|
||||
VALUE "OriginalFilename", "hyper.exe"
|
||||
VALUE "ProductName", "HyperRogue"
|
||||
VALUE "ProductVersion", "9.4n1"
|
||||
VALUE "ProductVersion", "10.0"
|
||||
END
|
||||
END
|
||||
|
||||
|
@ -255,6 +255,11 @@ hyperpoint mirrorif(const hyperpoint& V, bool b) {
|
||||
else return V;
|
||||
}
|
||||
|
||||
transmatrix mirrorif(const transmatrix& V, bool b) {
|
||||
if(b) return V*Mirror;
|
||||
else return V;
|
||||
}
|
||||
|
||||
// -1 if away, 0 if not away
|
||||
int away(const transmatrix& V2) {
|
||||
return intval(C0, V2 * xpush0(1)) > intval(C0, tC0(V2));
|
||||
@ -305,7 +310,7 @@ void drawrec(const heptspin& hs, int lev, hstate s, const transmatrix& V) {
|
||||
|
||||
if(dodrawcell(c)) {
|
||||
reclevel = maxreclevel - lev;
|
||||
drawcell(c, (hs.spin || purehepta) ? V1 * spin(hs.spin*2*M_PI/S7 + (purehepta ? M_PI:0)) : V1, hs.spin,
|
||||
drawcell(c, (hs.spin || purehepta) ? V1 * spin(hs.spin*2*M_PI/S7 + (purehepta ? M_PI:0)) : V1, 0,
|
||||
hs.mirrored);
|
||||
}
|
||||
|
||||
|
11
init.cpp
11
init.cpp
@ -1,6 +1,6 @@
|
||||
#define VER "9.4n2"
|
||||
#define VERNUM 9416
|
||||
#define VERNUM_HEX 0x9416
|
||||
#define VER "10.0"
|
||||
#define VERNUM 10000
|
||||
#define VERNUM_HEX 0xA000
|
||||
|
||||
#define GEN_M 0
|
||||
#define GEN_F 1
|
||||
@ -264,7 +264,7 @@ const char *loadlevel = NULL;
|
||||
#include "landgen.cpp"
|
||||
#include "orbs.cpp"
|
||||
#ifdef INV
|
||||
#include "closed/inventory.cpp"
|
||||
#include "inventory.cpp"
|
||||
#else
|
||||
bool inv::on;
|
||||
#endif
|
||||
@ -307,12 +307,13 @@ bool inv::on;
|
||||
#endif
|
||||
|
||||
bool fixseed = false;
|
||||
int startseed = 0;
|
||||
|
||||
void initAll() {
|
||||
ca::init();
|
||||
arg::read(1);
|
||||
srand(time(NULL));
|
||||
shrand(fixseed ? 0 : time(NULL));
|
||||
shrand(fixseed ? startseed : time(NULL));
|
||||
|
||||
achievement_init(); // not in ANDROID
|
||||
|
||||
|
356
landgen.cpp
356
landgen.cpp
@ -4,6 +4,19 @@
|
||||
|
||||
// land generation routines
|
||||
|
||||
int steplimit = 0;
|
||||
int cstep;
|
||||
|
||||
template<class... T>
|
||||
void limitgen(T... args) {
|
||||
if(steplimit) {
|
||||
cstep++;
|
||||
printf("%6d ", cstep);
|
||||
printf(args...);
|
||||
if(cstep == steplimit) buggyGeneration = true;
|
||||
}
|
||||
}
|
||||
|
||||
vector<cell*> buggycells;
|
||||
|
||||
cell *pathTowards(cell *pf, cell *pt) {
|
||||
@ -57,7 +70,7 @@ int isNative(eLand l, eMonster m) {
|
||||
case laAlchemist:
|
||||
return (m == moSlime) ? 2 : 0;
|
||||
|
||||
case laMirror:
|
||||
case laMirror: case laMirrored: case laMirrorWall: case laMirrorWall2: case laMirrored2:
|
||||
return (m == moEagle || m == moRanger || m == moMirror || m == moMirage) ? 1 : 0;
|
||||
|
||||
case laMotion:
|
||||
@ -217,7 +230,10 @@ eItem treasureType(eLand l) {
|
||||
case laDesert: return itSpice;
|
||||
|
||||
case laAlchemist: return itElixir;
|
||||
case laMirror: return itShard;
|
||||
|
||||
case laMirror: case laMirrored: case laMirrorWall: case laMirrorWall2: case laMirrored2:
|
||||
return itShard;
|
||||
|
||||
case laMotion: return itFeather;
|
||||
|
||||
case laGraveyard: return itBone;
|
||||
@ -310,7 +326,7 @@ eItem wanderingTreasure(cell *c) {
|
||||
return treasureType(l);
|
||||
}
|
||||
|
||||
#define ORBLINES 54
|
||||
#define ORBLINES 56
|
||||
|
||||
struct orbinfo {
|
||||
eLand l;
|
||||
@ -350,6 +366,7 @@ const orbinfo orbinfos[ORBLINES] = {
|
||||
{laOcean, 0, 3000, itOrbEmpathy},
|
||||
{laOcean, 0, 0, itOrbAir},
|
||||
{laPalace, 0, 4000, itOrbDiscord},
|
||||
{laPalace, 0, 0, itOrbFrog},
|
||||
{laZebra, 500, 2100, itOrbFrog},
|
||||
{laLivefjord, 0, 1800, itOrbFish},
|
||||
{laPrincessQuest, 0, 200, itOrbLove},
|
||||
@ -374,6 +391,7 @@ const orbinfo orbinfos[ORBLINES] = {
|
||||
{laReptile, 500, 2100, itOrbDash},
|
||||
{laBull, 720, 3000, itOrbHorns},
|
||||
{laPrairie, 0, 3500, itOrbBull},
|
||||
{laWhirlpool, 0, 0, itOrbSafety},
|
||||
{laWhirlpool, 0, 2000, itOrbWater}, // must be last because it generates a boat
|
||||
};
|
||||
|
||||
@ -635,7 +653,8 @@ bool landUnlocked(eLand l) {
|
||||
return true;
|
||||
|
||||
case laMirror: case laMinefield: case laPalace:
|
||||
case laOcean: case laLivefjord:
|
||||
case laOcean: case laLivefjord: case laMirrored: case laMirrorWall: case laMirrorWall2:
|
||||
case laMirrored2:
|
||||
return gold() >= R30;
|
||||
|
||||
case laCaribbean: case laWhirlpool:
|
||||
@ -926,6 +945,10 @@ void setbarrier(cell *c) {
|
||||
else if(c->barleft == laHaunted || c->barright == laHaunted) {
|
||||
c->land = laHauntedWall;
|
||||
}
|
||||
else if(c->barleft == laMirrored2 || c->barright == laMirrored2)
|
||||
c->land = laMirrorWall2;
|
||||
else if(c->barleft == laMirrored || c->barright == laMirrored)
|
||||
c->land = laMirrorWall;
|
||||
else {
|
||||
c->wall = waBarrier;
|
||||
c->land = laBarrier;
|
||||
@ -1016,24 +1039,36 @@ bool buildPrizeMirror(cell *c, int freq) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void placePrizeOrb(cell *c) {
|
||||
eLand getPrizeLand(cell *c = cwt.c) {
|
||||
eLand l = c->land;
|
||||
if(isElemental(l)) l = laElementalWall;
|
||||
if(l == laPalace && princess::dist(c) < OUT_OF_PRISON)
|
||||
l = laPrincessQuest;
|
||||
return l;
|
||||
}
|
||||
|
||||
void placePrizeOrb(cell *c) {
|
||||
if(peace::on) return;
|
||||
|
||||
eLand l = getPrizeLand(c);
|
||||
|
||||
// these two lands would have too much orbs according to normal rules
|
||||
if(l == laPalace && hrand(100) >= 20) return;
|
||||
if(l == laPrincessQuest && hrand(100) >= 20) return;
|
||||
if(l == laGraveyard && hrand(100) >= 15) return;
|
||||
if(l == laBurial && hrand(100) >= 10) return;
|
||||
if(l == laLivefjord && hrand(100) >= 35) return;
|
||||
if(l == laMinefield && hrand(100) >= 25) return;
|
||||
if(l == laElementalWall && hrand(100) >= 25) return;
|
||||
|
||||
if(l == laPalace && princess::dist(c) < OUT_OF_PRISON)
|
||||
l = laPrincessQuest;
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
if(inv::on && oi.orb != itOrbYendor) return;
|
||||
|
||||
if(inv::on) {
|
||||
if(oi.orb == itOrbYendor && items[itHell] >= 100) ;
|
||||
else continue;
|
||||
}
|
||||
|
||||
eOrbLandRelation olr = getOLR(oi.orb, l);
|
||||
if(olr != olrPrize25 && olr != olrPrize3) continue;
|
||||
int treas = items[treasureType(oi.l)];
|
||||
@ -1069,7 +1104,10 @@ void placeLocalOrbs(cell *c) {
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
if(oi.l != l) continue;
|
||||
if(inv::on && (oi.orb != itOrbYendor)) continue;
|
||||
if(inv::on) {
|
||||
if(oi.orb != itOrbYendor) continue;
|
||||
if(items[itHell] < 25) continue;
|
||||
}
|
||||
if(yendor::on && (oi.orb == itOrbSafety || oi.orb == itOrbYendor))
|
||||
continue;
|
||||
if(!oi.lchance) continue;
|
||||
@ -1093,7 +1131,12 @@ void placeCrossroadOrbs(cell *c) {
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
if(!oi.gchance) continue;
|
||||
if(inv::on && oi.orb != itOrbSafety && oi.orb != itOrbYendor) return;
|
||||
|
||||
if(inv::on) {
|
||||
if(oi.orb == itOrbYendor && items[itHell] >= 50) ;
|
||||
else if(oi.orb == itOrbSafety && items[itFeather] >= 25) ;
|
||||
else continue;
|
||||
}
|
||||
int treas = items[treasureType(oi.l)] * landMultiplier(oi.l);
|
||||
if(tactic::on && isCrossroads(tactic::lasttactic)) {
|
||||
if(oi.orb == itOrbYendor || oi.orb == itOrbSummon || oi.orb == itOrbFish || oi.orb == itOrbDigging || oi.orb == itOrbLove || oi.orb == itOrbLuck)
|
||||
@ -1117,7 +1160,13 @@ void placeOceanOrbs(cell *c) {
|
||||
if(peace::on) return;
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
if(inv::on && oi.orb != itOrbSafety && oi.orb != itOrbYendor) return;
|
||||
|
||||
if(inv::on) {
|
||||
if(oi.orb == itOrbYendor && items[itHell] >= 50) ;
|
||||
else if(oi.orb == itOrbSafety && items[itFeather] >= 25) ;
|
||||
else continue;
|
||||
}
|
||||
|
||||
if(items[treasureType(oi.l)] * landMultiplier(oi.l) < 10) continue;
|
||||
if(!oi.gchance) continue;
|
||||
if(oi.orb == itOrbLife) continue; // useless
|
||||
@ -1193,8 +1242,28 @@ void extendcheck(cell *c) {
|
||||
raiseBuggyGeneration(c, "extend error");
|
||||
}
|
||||
}
|
||||
|
||||
bool oldmirror;
|
||||
|
||||
bool inmirror(eLand l) {
|
||||
return l == laMirrored || l == laMirrorWall2 || l == laMirrored2;
|
||||
}
|
||||
|
||||
bool inmirror(cell *c) {
|
||||
return inmirror(c->land);
|
||||
}
|
||||
|
||||
bool inmirror(const cellwalker& cw) {
|
||||
return inmirror(cw.c->land);
|
||||
}
|
||||
|
||||
bool mirrorwall(cell *c) {
|
||||
return c->barleft == laMirrored || c->barright == laMirrored;
|
||||
}
|
||||
|
||||
void extendBarrierFront(cell *c) {
|
||||
limitgen("extend front %p\n", c);
|
||||
if(buggyGeneration) return;
|
||||
int ht = c->landparam;
|
||||
extendcheck(c);
|
||||
|
||||
@ -1205,7 +1274,8 @@ void extendBarrierFront(cell *c) {
|
||||
bb.c->barleft = c->barleft;
|
||||
bb.c->barright = c->barright;
|
||||
setbarrier(bb.c);
|
||||
bb.c->landparam = (ht-4);
|
||||
if(!mirrorwall(bb.c))
|
||||
bb.c->landparam = (ht-4);
|
||||
//printf("[A heat %d]\n", ht-4);
|
||||
|
||||
cwspin(bb, 2); cwstep(bb); setland(bb.c, c->barleft); cwstep(bb);
|
||||
@ -1216,11 +1286,15 @@ void extendBarrierFront(cell *c) {
|
||||
bb.c->barleft = c->barright;
|
||||
bb.c->barright = c->barleft;
|
||||
setbarrier(bb.c);
|
||||
bb.c->landparam = (ht-4)^2;
|
||||
if(!mirrorwall(bb.c))
|
||||
bb.c->landparam = (ht-4)^2;
|
||||
//printf("[B heat %d]\n", (ht-4)^2);
|
||||
cwspin(bb, 3); cwstep(bb);
|
||||
|
||||
bb.c->landparam = ht ^ 2;
|
||||
bb.c->barleft = c->barleft;
|
||||
bb.c->barright = c->barright;
|
||||
if(!mirrorwall(bb.c))
|
||||
bb.c->landparam = ht ^ 2;
|
||||
}
|
||||
|
||||
//printf("[C heat %d]\n", (ht)^2);
|
||||
@ -1238,6 +1312,8 @@ void extendBarrierFront(cell *c) {
|
||||
}
|
||||
|
||||
void extendBarrierBack(cell *c) {
|
||||
limitgen("extend back %p\n", c);
|
||||
if(buggyGeneration) return;
|
||||
int ht = c->landparam;
|
||||
extendcheck(c);
|
||||
|
||||
@ -1248,7 +1324,8 @@ void extendBarrierBack(cell *c) {
|
||||
bb.c->bardir = bb.spin;
|
||||
bb.c->barleft = c->barright;
|
||||
bb.c->barright = c->barleft;
|
||||
bb.c->landparam = ht ^ 11;
|
||||
if(!mirrorwall(bb.c))
|
||||
bb.c->landparam = ht ^ 11;
|
||||
extendcheck(bb.c);
|
||||
//printf("[D heat %d]\n", (ht^11));
|
||||
|
||||
@ -1257,7 +1334,8 @@ void extendBarrierBack(cell *c) {
|
||||
cwstep(bb);
|
||||
bb.c->barleft = c->barright;
|
||||
bb.c->barright = c->barleft;
|
||||
bb.c->landparam = (ht^11)-4;
|
||||
if(!mirrorwall(bb.c))
|
||||
bb.c->landparam = (ht^11)-4;
|
||||
cwstep(bb);
|
||||
}
|
||||
//printf("[E heat %d]\n", (ht^11));
|
||||
@ -1266,11 +1344,13 @@ void extendBarrierBack(cell *c) {
|
||||
extendBarrier(bb.c);
|
||||
}
|
||||
|
||||
eLand oppositeElement(eLand l) {
|
||||
eLand oppositeElement(eLand l, eLand l2) {
|
||||
if(l == laEFire) return laEWater;
|
||||
if(l == laEWater) return laEFire;
|
||||
if(l == laEAir) return laEEarth;
|
||||
if(l == laEEarth) return laEAir;
|
||||
if(l == laMirror && l2 == laMirrored) return laMirrored2;
|
||||
if(l == laMirrored2 && l2 == laMirrored) return laMirror;
|
||||
return l;
|
||||
}
|
||||
|
||||
@ -1353,7 +1433,14 @@ void extendCR5(cell *c) {
|
||||
}
|
||||
}
|
||||
|
||||
bool isbar4(cell *c) {
|
||||
return
|
||||
c->wall == waBarrier || c->land == laElementalWall ||
|
||||
c->land == laMirrorWall || c->land == laMirrorWall2;
|
||||
}
|
||||
|
||||
void extendBarrier(cell *c) {
|
||||
limitgen("extend barrier %p\n", c);
|
||||
if(buggyGeneration) return;
|
||||
|
||||
if(c->barleft == NOWALLSEP_USED) return;
|
||||
@ -1361,7 +1448,8 @@ void extendBarrier(cell *c) {
|
||||
extendcheck(c);
|
||||
|
||||
// printf("build barrier at %p", c);
|
||||
if(c->land == laBarrier || c->land == laElementalWall || c->land == laHauntedWall || c->land == laOceanWall) {
|
||||
if(c->land == laBarrier || c->land == laElementalWall || c->land == laHauntedWall || c->land == laOceanWall ||
|
||||
c->land == laMirrorWall || c->land == laMirrorWall2) {
|
||||
// printf("-> ready\n");
|
||||
return;
|
||||
}
|
||||
@ -1376,14 +1464,40 @@ void extendBarrier(cell *c) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool firstmirror =
|
||||
(c->barleft == laMirrored || c->barright == laMirrored) &&
|
||||
c->barleft != laMirrored2 && c->barright != laMirrored2;
|
||||
|
||||
if(firstmirror && c->barleft == laMirror && hrand(100) < 60) {
|
||||
cellwalker cw(c, c->bardir);
|
||||
if(!purehepta) cwstep(cw);
|
||||
if(cw.c->land != laMirrorWall)
|
||||
if(buildBarrier6(cw, 1)) return;
|
||||
}
|
||||
|
||||
if(firstmirror && (purehepta?c->barleft == laMirror : c->barright == laMirror) && hrand(100) < 60) {
|
||||
cellwalker cw(c, c->bardir);
|
||||
if(purehepta) {
|
||||
cwspin(cw, -3); cwstep(cw); cwspin(cw, -3);
|
||||
// cwspin(cw, 3); cwstep(cw); cwspin(cw, -2); cwstep(cw); cwspin(cw, 3);
|
||||
}
|
||||
else {
|
||||
cwstep(cw); cwspin(cw, 3); cwstep(cw); cwspin(cw, -1); // check this
|
||||
}
|
||||
if(buildBarrier6(cw, 2)) return;
|
||||
}
|
||||
|
||||
if(((c->barleft == laCrossroads3 || c->barright == laCrossroads3) && hrand(100) < 66) ||
|
||||
(isElemental(c->barleft) && isElemental(c->barright) && hrand(100) < 25)) {
|
||||
(isElemental(c->barleft) && isElemental(c->barright) && hrand(100) < 75)
|
||||
|| (firstmirror && hrand(100) < 60)
|
||||
) {
|
||||
|
||||
cellwalker cw(c, c->bardir);
|
||||
if(purehepta) {
|
||||
cwstep(cw); if(cw.c->wall == waBarrier || cw.c->land == laElementalWall) {
|
||||
cwstep(cw);
|
||||
if(isbar4(cw.c)) {
|
||||
cwstep(cw); cwspin(cw, 3); cwstep(cw); cwspin(cw, -1); cwstep(cw);
|
||||
bool b = buildBarrier4(cw.c, cw.spin, 2, oppositeElement(c->barleft), c->barright);
|
||||
bool b = buildBarrier4(cw.c, cw.spin, 2, oppositeElement(c->barleft, c->barright), c->barright);
|
||||
if(b) return;
|
||||
}
|
||||
else {
|
||||
@ -1394,9 +1508,9 @@ void extendBarrier(cell *c) {
|
||||
else {
|
||||
cwspin(cw, 3); cwstep(cw);
|
||||
cell *cp = cwpeek(cw, 4);
|
||||
if(cp->wall != waBarrier && cp->land != laElementalWall) {
|
||||
if(!isbar4(cp)) {
|
||||
cwspin(cw, 2); cwstep(cw);
|
||||
bool b = buildBarrier4(cw.c, cw.spin, 2, oppositeElement(c->barleft), c->barright);
|
||||
bool b = buildBarrier4(cw.c, cw.spin, 2, oppositeElement(c->barleft, c->barright), c->barright);
|
||||
if(b) return;
|
||||
}
|
||||
else {
|
||||
@ -1602,6 +1716,8 @@ eLand getNewLand(eLand old) {
|
||||
|
||||
eLand l = callhandlers(laNone, hooks_nextland, old);
|
||||
if(l) return l;
|
||||
|
||||
if(old == laMirror && !oldmirror && hrand(10)) return laMirrored;
|
||||
|
||||
if(cheatdest != old) if(!isCyclic(cheatdest) && !isTechnicalLand(cheatdest)) return cheatdest;
|
||||
|
||||
@ -1927,7 +2043,7 @@ void buildBarrierForce(cell *c, int d, eLand l) {
|
||||
landcount[newland]++;
|
||||
if(d == 4 || d == 5 || d == 6) c->barleft = oldland, c->barright = newland;
|
||||
else c->barleft = newland, c->barright = oldland;
|
||||
c->landparam = 40;
|
||||
if(!mirrorwall(c)) c->landparam = 40;
|
||||
extendcheck(c);
|
||||
}
|
||||
|
||||
@ -1939,7 +2055,124 @@ void buildBarrier(cell *c, int d, eLand l) {
|
||||
buildBarrierForce(c, d, l);
|
||||
}
|
||||
|
||||
bool buildBarrier6(cellwalker cw, int type) {
|
||||
limitgen("build6 %p/%d (%d)\n", cw.c, cw.spin, type);
|
||||
|
||||
cellwalker b[4];
|
||||
for(int i=0; i<4; i++) b[i] = cw;
|
||||
|
||||
if(buggyGeneration) return true;
|
||||
|
||||
if(!purehepta) {
|
||||
cwstep(b[0]);
|
||||
cwspin(b[1], 1); cwstep(b[1]); cwspin(b[1], 3); cwstep(b[1]);
|
||||
cwspin(b[2], 4); cwstep(b[2]);
|
||||
cwspin(b[3], 3); cwstep(b[3]); cwspin(b[3], 3); cwstep(b[3]);
|
||||
}
|
||||
else {
|
||||
cwspin(b[1], 3); cwstep(b[1]); cwspin(b[1], 3);
|
||||
cwspin(b[2], -2); cwstep(b[2]); cwspin(b[2], -3);
|
||||
cwspin(b[3], -3); cwstep(b[3]); cwspin(b[3], 2); cwstep(b[3]); cwspin(b[3],-3);
|
||||
if(type == 1 && b[3].c->land != laMirrorWall) return false;
|
||||
if(type == 2 && cwpeek(b[1], 0)->land != laMirrorWall) return false;
|
||||
// if(type == 2 && b[2].c->land != laMirrorWall) return false;
|
||||
}
|
||||
|
||||
if(false) {
|
||||
for(int z=0; z<4; z++) {
|
||||
printf("%p/%d\n", b[z].c, b[z].spin);
|
||||
b[z].c->wall = waStrandedBoat; b[z].c->land = laAlchemist;
|
||||
b[z].c->mondir = b[z].spin;
|
||||
b[z].c->mpdist = 7;
|
||||
b[z].c->item = eItem(1+z);
|
||||
buggyGeneration = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(type == 1) {
|
||||
if(!(purehepta?checkBarriersFront:checkBarriersBack)(b[1], 6, true)) return false;
|
||||
if(!(purehepta?checkBarriersFront:checkBarriersBack)(b[2], 6, true)) return false;
|
||||
}
|
||||
else {
|
||||
if(!(purehepta?checkBarriersFront:checkBarriersBack)(b[0], 6, true)) return false;
|
||||
if(!(purehepta?checkBarriersFront:checkBarriersBack)(b[3], 6, true)) return false;
|
||||
}
|
||||
|
||||
for(int d=0; d<4; d++) {
|
||||
b[d].c->bardir = b[d].spin;
|
||||
|
||||
if(purehepta) {
|
||||
b[0].c->barleft = laMirrored, b[0].c->barright = laMirrored2;
|
||||
b[1].c->barleft = laMirror, b[1].c->barright = laMirrored;
|
||||
b[2].c->barleft = laMirrored2, b[2].c->barright = laMirrored;
|
||||
b[3].c->barleft = laMirrored, b[3].c->barright = laMirror;
|
||||
}
|
||||
else {
|
||||
b[0].c->barleft = laMirror, b[0].c->barright = laMirrored;
|
||||
b[1].c->barleft = laMirrored, b[1].c->barright = laMirror;
|
||||
b[2].c->barleft = laMirrored, b[2].c->barright = laMirrored2;
|
||||
b[3].c->barleft = laMirrored2, b[3].c->barright = laMirrored;
|
||||
}
|
||||
|
||||
(purehepta?extendBarrierFront:extendBarrierBack)(b[d].c);
|
||||
}
|
||||
|
||||
if(purehepta && false) {
|
||||
for(int a=0; a<4; a++)
|
||||
extendBarrierBack(cwpeek(b[a],0));
|
||||
}
|
||||
|
||||
if(!purehepta) {
|
||||
setland(cwpeek(cw, 1), laMirrorWall);
|
||||
setland(cwpeek(cw, 2), laMirrored);
|
||||
setland(cwpeek(cw, 3), laMirrorWall2);
|
||||
setland(cwpeek(cw, 4), laMirrorWall2);
|
||||
setland(cwpeek(cw, 5), laMirrored);
|
||||
setland(cwpeek(cw, 0), laMirrorWall);
|
||||
setland(cwpeek(b[0], 2), laMirrored);
|
||||
setland(cwpeek(b[3], 6), laMirrored2);
|
||||
setland(cwpeek(b[3], 5), laMirrored2);
|
||||
setland(cwpeek(b[1], -1), laMirrored);
|
||||
setland(cwpeek(b[2], -2), laMirrored);
|
||||
setland(cwpeek(b[1], -2), laMirrored);
|
||||
setland(cwpeek(b[0], -2), laMirror);
|
||||
cw.c->land = laMirrorWall;
|
||||
cw.c->wall = waMirrorWall;
|
||||
cw.c->landparam = 1;
|
||||
}
|
||||
else {
|
||||
setland(cw.c, laMirrorWall2);
|
||||
setland(cwpeek(cw, 0), laMirrorWall2);
|
||||
setland(cwpeek(cw, 1), laMirrored);
|
||||
setland(cwpeek(cw, 2), laMirrored);
|
||||
setland(cwpeek(cw, 3), laMirrorWall);
|
||||
setland(cwpeek(cw, 4), laMirrored);
|
||||
setland(cwpeek(cw, 5), laMirrorWall2);
|
||||
setland(cwpeek(cw, 6), laMirrored2);
|
||||
|
||||
setland(cwpeek(b[1], 0), laMirrorWall);
|
||||
setland(cwpeek(b[1], 1), laMirror);
|
||||
setland(cwpeek(b[1], 2), laMirrorWall);
|
||||
setland(cwpeek(b[1], 6), laMirrored);
|
||||
|
||||
cellwalker cf = b[0];
|
||||
cwstep(cf);
|
||||
setland(cwpeek(cf, -2), laMirrored);
|
||||
|
||||
cf = b[3];
|
||||
cwstep(cf);
|
||||
setland(cwpeek(cf, -2), laMirrored);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) {
|
||||
limitgen("build4 %p\n", c);
|
||||
if(buggyGeneration) return true;
|
||||
d %= 7;
|
||||
cellwalker b1(c, d);
|
||||
|
||||
@ -1978,8 +2211,8 @@ bool buildBarrier4(cell *c, int d, int mode, eLand ll, eLand lr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
eLand xl = oppositeElement(ll);
|
||||
eLand xr = oppositeElement(lr);
|
||||
eLand xl = oppositeElement(ll, lr);
|
||||
eLand xr = oppositeElement(lr, ll);
|
||||
|
||||
c->bardir = d, c->barleft = ll, c->barright = lr; extendBarrierBack(c);
|
||||
|
||||
@ -2235,6 +2468,9 @@ int coastval(cell *c, eLand base) {
|
||||
return 0;
|
||||
if(c->land != laGraveyard && c->land != laHauntedBorder) return 30;
|
||||
}
|
||||
else if(base == laMirrored) {
|
||||
if(!inmirror(c)) return 0;
|
||||
}
|
||||
else {
|
||||
if(c->land == laOceanWall || c->land == laCaribbean || c->land == laWhirlpool ||
|
||||
c->land == laLivefjord || c->land == laWarpSea || c->land == laKraken)
|
||||
@ -2303,6 +2539,7 @@ void buildEquidistant(cell *c) {
|
||||
// buggycells.push_back(c);
|
||||
}
|
||||
if(b == laHauntedBorder) b = laGraveyard;
|
||||
if(inmirror(b)) b = laMirrored;
|
||||
int mcv = UNKNOWN;
|
||||
|
||||
// find the lowest coastval
|
||||
@ -2326,7 +2563,7 @@ void buildEquidistant(cell *c) {
|
||||
for(int i=0; i<c->type; i++)
|
||||
if(coastval(c->mov[i], b) == mcv)
|
||||
qcv++, sid = i;
|
||||
|
||||
|
||||
// if(generatingEquidistant) printf("qcv=%d mcv=%d\n", qcv, mcv);
|
||||
if(qcv >= 2) c->landparam = mcv+1; // (mcv == UNKNOWN ? UNKNOWN : mcv+1);
|
||||
else {
|
||||
@ -2827,6 +3064,10 @@ void setLandEuclid(cell *c) {
|
||||
}
|
||||
}
|
||||
|
||||
#define INVLUCK (items[itOrbLuck] && inv::on)
|
||||
#define I2000 (INVLUCK?600:2000)
|
||||
#define I10000 (INVLUCK?3000:10000)
|
||||
|
||||
void buildBigStuff(cell *c, cell *from) {
|
||||
if(sphere || quotient) return;
|
||||
bool deepOcean = false;
|
||||
@ -2867,7 +3108,7 @@ void buildBigStuff(cell *c, cell *from) {
|
||||
else if(c->type == 7 && c->land == laCrossroads4 && hrand(10000) < 7000 && c->land &&
|
||||
buildBarrierNowall(c, getNewLand(laCrossroads4))) ;
|
||||
|
||||
else if(c->type == 7 && hrand(10000) < 20 && !generatingEquidistant && !yendor::on && !tactic::on && !isCrossroads(c->land) && gold() >= R200 &&
|
||||
else if(c->type == 7 && hrand(I10000) < 20 && !generatingEquidistant && !yendor::on && !tactic::on && !isCrossroads(c->land) && gold() >= R200 &&
|
||||
!isSealand(c->land) && !isHaunted(c->land) && !isGravityLand(c->land) &&
|
||||
(c->land != laRlyeh || rlyehComplete()) &&
|
||||
c->land != laTortoise && c->land != laPrairie && c->land &&
|
||||
@ -2891,8 +3132,9 @@ void buildBigStuff(cell *c, cell *from) {
|
||||
}
|
||||
}
|
||||
|
||||
else if(c->type == 7 && c->land && hrand(10000) < (
|
||||
else if(c->type == 7 && c->land && hrand(I10000) < (
|
||||
showoff ? (cwt.c->mpdist > 7 ? 0 : 10000) :
|
||||
inmirror(c) ? 0 :
|
||||
isGravityLand(c->land) ? 0 :
|
||||
generatingEquidistant ? 0 :
|
||||
c->land == laPrairie ? 0 :
|
||||
@ -2915,6 +3157,7 @@ void buildBigStuff(cell *c, cell *from) {
|
||||
(c->land == laGraveyard && items[itBone] >= 10) ? 120 :
|
||||
c->land == laOcean ? (deepOcean ? (purehepta ? 250 : 2000) : 0) :
|
||||
c->land == laDragon ? 120 :
|
||||
(c->land == laMirror && !oldmirror) ? 6000 :
|
||||
50))
|
||||
{
|
||||
|
||||
@ -2927,7 +3170,7 @@ void buildBigStuff(cell *c, cell *from) {
|
||||
}
|
||||
|
||||
if((!chaosmode) && bearsCamelot(c->land) && c->type == 7 &&
|
||||
(quickfind(laCamelot) || peace::on || (hrand(2000) < 200 &&
|
||||
(quickfind(laCamelot) || peace::on || (hrand(I2000) < 200 &&
|
||||
items[itEmerald] >= U5 && !tactic::on))) {
|
||||
int rtr = newRoundTableRadius();
|
||||
heptagon *alt = createAlternateMap(c, rtr+14, hsOrigin);
|
||||
@ -2942,18 +3185,18 @@ void buildBigStuff(cell *c, cell *from) {
|
||||
// buildbigstuff
|
||||
|
||||
if(c->land == laRlyeh && c->type == 7 &&
|
||||
(quickfind(laTemple) || peace::on || (hrand(2000) < 100 &&
|
||||
(quickfind(laTemple) || peace::on || (hrand(I2000) < 100 &&
|
||||
items[itStatue] >= U5 && !randomPatternsMode &&
|
||||
!tactic::on && !yendor::on)))
|
||||
createAlternateMap(c, 2, hsA);
|
||||
|
||||
if(c->land == laJungle && c->type == 7 &&
|
||||
(quickfind(laMountain) || (hrand(2000) < 100 &&
|
||||
(quickfind(laMountain) || (hrand(I2000) < 100 &&
|
||||
!randomPatternsMode && !tactic::on && !yendor::on && landUnlocked(laMountain))))
|
||||
createAlternateMap(c, 2, hsA);
|
||||
|
||||
if(c->land == laOvergrown && c->type == 7 &&
|
||||
(quickfind(laClearing) || (hrand(2000) < 25 &&
|
||||
(quickfind(laClearing) || (hrand(I2000) < 25 &&
|
||||
!randomPatternsMode && items[itMutant] >= U5 &&
|
||||
!tactic::on && !yendor::on))) {
|
||||
heptagon *h = createAlternateMap(c, 2, hsA);
|
||||
@ -2977,8 +3220,11 @@ void buildBigStuff(cell *c, cell *from) {
|
||||
(princess::forceMouse ? (from && from->pathdist != INF) :
|
||||
(hrand(2000) < (peace::on ? 100 : 20))) &&
|
||||
!c->master->alt &&
|
||||
(princess::challenge || kills[moVizier] || peace::on) && !tactic::on && !yendor::on)
|
||||
createAlternateMap(c, 141, hsOrigin, waPalace);
|
||||
(princess::challenge || kills[moVizier] || peace::on) && !tactic::on && !yendor::on) {
|
||||
createAlternateMap(c, PRADIUS0, hsOrigin, waPalace);
|
||||
celllister cl(c, 5, 1000000, NULL);
|
||||
for(cell *c: cl.lst) if(c->master->alt) generateAlts(c->master);
|
||||
}
|
||||
}
|
||||
|
||||
if(hasbardir(c)) extendBarrier(c);
|
||||
@ -3265,6 +3511,8 @@ void setdist(cell *c, int d, cell *from) {
|
||||
|
||||
if(d <= 3) lastexplore = shmup::on ? shmup::curtime : turncount;
|
||||
|
||||
oldmirror = euclid || chaosmode || yendor::on || yendor::generating;
|
||||
|
||||
if(buggyGeneration) {
|
||||
if(d < BARLEV) for(int i=0; i<c->type; i++) {
|
||||
setdist(createMov(c, i), d+(purehepta?2:1), c);
|
||||
@ -3310,6 +3558,8 @@ void setdist(cell *c, int d, cell *from) {
|
||||
if(d == BARLEV && !euclid && c != cwt.c)
|
||||
buildBigStuff(c, from);
|
||||
|
||||
if(buggyGeneration) return;
|
||||
|
||||
if(d < 10) {
|
||||
explore[d]++;
|
||||
exploreland[d][c->land]++;
|
||||
@ -3322,6 +3572,9 @@ void setdist(cell *c, int d, cell *from) {
|
||||
if(d == BARLEV-2 && c->land == laOcean)
|
||||
buildEquidistant(c);
|
||||
|
||||
if(d == BARLEV-2 && inmirror(c))
|
||||
buildEquidistant(c);
|
||||
|
||||
if(d == BARLEV-2 && (c->land == laGraveyard || c->land == laHauntedBorder || c->land == laHaunted))
|
||||
buildEquidistant(c);
|
||||
|
||||
@ -3908,7 +4161,7 @@ void setdist(cell *c, int d, cell *from) {
|
||||
|
||||
if(c->land == laPalace && !euclid && c->master->alt) {
|
||||
int d = celldistAlt(c);
|
||||
if(d <= 150) generateAlts(c->master);
|
||||
if(d <= PRADIUS1) generateAlts(c->master);
|
||||
}
|
||||
|
||||
if((bearsCamelot(c->land) && !euclid && !quotient) || c->land == laCamelot)
|
||||
@ -4734,9 +4987,12 @@ void setdist(cell *c, int d, cell *from) {
|
||||
princess::getPrisonInfo(c) &&
|
||||
(euclid || (princess::getPrisonInfo(c)->bestdist < 6 && princess::getPrisonInfo(c)->princess))) {
|
||||
c->monst = moMouse;
|
||||
addMessage(XLAT("You hear a distant squeak!"));
|
||||
playSound(c, "mousesqueak");
|
||||
drawBigFlash(c);
|
||||
if(!princess::squeaked) {
|
||||
addMessage(XLAT("You hear a distant squeak!"));
|
||||
playSound(c, "mousesqueak");
|
||||
drawBigFlash(c);
|
||||
princess::squeaked = true;
|
||||
}
|
||||
/* {
|
||||
cell *c2= c;
|
||||
z:
|
||||
@ -5024,7 +5280,7 @@ void setdist(cell *c, int d, cell *from) {
|
||||
else {
|
||||
if(hyperstonesUnlocked() && hrand(25000) < min(PT(tkills(), 2000), 5000) && notDippingFor(itHyperstone))
|
||||
c->item = itHyperstone;
|
||||
if(hrand(4000) < items[itHyperstone] + 2 * items[itHolyGrail] && !c->monst) {
|
||||
if(hrand(4000) < items[itHyperstone] && !c->monst) {
|
||||
// only interesting monsters here!
|
||||
eMonster cm = crossroadsMonster();
|
||||
if(cm == moIvyRoot) buildIvy(c, 0, c->type);
|
||||
@ -5035,14 +5291,19 @@ void setdist(cell *c, int d, cell *from) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(c->land == laMirrored || c->land == laMirrorWall || c->land == laMirrorWall2 ||
|
||||
c->land == laMirrored2)
|
||||
c->wall = waMirrorWall;
|
||||
if(c->land == laMirror) {
|
||||
if((purehepta?pseudohept(c):!ishept(c)) && hrand(5000) < 120 && notDippingFor(itShard))
|
||||
int freqt = oldmirror ? 1 : 4;
|
||||
int freqm = (oldmirror || cwt.c->land != laMirror) ? 1 : 30;
|
||||
if((purehepta?pseudohept(c):!ishept(c)) && hrand(5000/freqt) < 120 && notDippingFor(itShard))
|
||||
c->wall = hrand(2) ? waMirror : waCloud;
|
||||
else if(ishept(c) && hrand(5000) < 10 * PRIZEMUL)
|
||||
else if(ishept(c) && hrand(5000/freqt) < 10 * PRIZEMUL)
|
||||
placePrizeOrb(c);
|
||||
else if(hrand(12000) < 8 + items[itShard] + hard)
|
||||
else if(hrand(12000/freqt) < 8 + items[itShard] + hard)
|
||||
c->monst = moRanger;
|
||||
else if(hrand(60000) < 8 + items[itShard] + hard)
|
||||
else if(hrand(60000/freqm) < 8 + items[itShard] + hard)
|
||||
c->monst = moEagle;
|
||||
}
|
||||
if(c->land == laGraveyard) {
|
||||
@ -5186,14 +5447,14 @@ void setdist(cell *c, int d, cell *from) {
|
||||
|
||||
bool wchance(int a, int of) {
|
||||
of *= 10;
|
||||
a += yendor::hardness() + items[itHolyGrail] + 1;
|
||||
a += yendor::hardness() + 1;
|
||||
if(isCrossroads(cwt.c->land))
|
||||
a+= items[itHyperstone] * 10;
|
||||
|
||||
//if(cwt.c->land == laWhirlwind && !nowhirl) a += items[itWindstone] * 3;
|
||||
|
||||
for(int i=0; i<ittypes; i++) if(itemclass(eItem(i)) == IC_TREASURE)
|
||||
a = max(a, (items[i]-10) / 10);
|
||||
a = max(a, (items[i]-R10) / 10);
|
||||
return hrand(a+of) < a;
|
||||
}
|
||||
|
||||
@ -5298,6 +5559,7 @@ void wandering() {
|
||||
while(first7 < size(dcal)) {
|
||||
int i = first7 + hrand(size(dcal) - first7);
|
||||
cell *c = dcal[i];
|
||||
if(inmirror(c)) continue;
|
||||
|
||||
if(smallbounded && !c->item && hrand(5) == 0 && c->land != laHalloween) {
|
||||
if(passable(c, NULL, 0) || euclidland == laKraken) {
|
||||
@ -5327,7 +5589,7 @@ void wandering() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ghostcount && !c->monst) {
|
||||
if(ghostcount && !c->monst && !inmirror(c)) {
|
||||
c->monst = moGhost;
|
||||
playSeenSound(c);
|
||||
ghostcount--;
|
||||
|
@ -7,12 +7,12 @@
|
||||
#define GEN_N 2
|
||||
#define GEN_O 3
|
||||
|
||||
using namespace std;
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
using namespace std;
|
||||
|
||||
template<class T> int size(T x) { return x.size(); }
|
||||
|
||||
|
251
language-pl.cpp
251
language-pl.cpp
@ -346,7 +346,7 @@ S("Hyperstone Quest: collect at least %3 %1 in %the2", "Misja alternatywna: znaj
|
||||
S("Hyperstone Quest completed!", "Misja alternatywna zakończona!")
|
||||
S("Look for the Orbs of Yendor in Hell or in the Crossroads!", "Szukaj Sfer Yendoru w Piekle albo na Skrzyżowaniu!")
|
||||
S("Unlock the Orb of Yendor!", "Otwórz Sferę Yendoru!")
|
||||
S("Defeat 100 enemies to access the Graveyard", "Pokonaj 100 przeciwników, by trafić na Cmentarz")
|
||||
S("Defeat %1 enemies to access the Graveyard", "Pokonaj %1 przeciwników, by trafić na Cmentarz")
|
||||
S("(press ESC during the game to review your quest)", "(naciśnij ESC w trakcie gry, by zobaczyć stan swojej misji)")
|
||||
S("you have cheated %1 times", "liczba oszustw: %1")
|
||||
S("%1 turns (%2)", "kolejek: %1 (%2)")
|
||||
@ -5440,19 +5440,31 @@ S(
|
||||
"Naciśnij '5' by opuścić podręcznik."
|
||||
)
|
||||
|
||||
#undef Orb
|
||||
|
||||
/*
|
||||
// for 10.0
|
||||
*/
|
||||
|
||||
S("configure keys/joysticks", "konfiguracja klawiszy/joysticka")
|
||||
S("Press F5 or 'o' to try again!", "Naciśnij F5 lub 'o' by spróbować jeszcze raz!")
|
||||
S("peaceful mode", "tryb pokojowy")
|
||||
S("inventory mode", "tryb inwentarza")
|
||||
S("inventory", "sfery")
|
||||
// Orb Strategy mode
|
||||
S("Orb Strategy mode", "tryb strategii sfer")
|
||||
|
||||
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",
|
||||
|
||||
"Grasz w trybie strategii sfer. Zebrane skarby dają Ci "
|
||||
"dostęp do magicznych mocy. W tym trybie wymagania "
|
||||
"są generalnie wyższe, i niektóre krainy i misje "
|
||||
"dają Ci bardzo potężne Sfery Lustra.\n")
|
||||
|
||||
S("The treasure gives your magical powers!", "Skarby dają Ci moce magiczne!")
|
||||
S("Press 'i' to access your magical powers.", "Naciśnij 'i', by użyć mocy.")
|
||||
S("inventory", "Twoje sfery")
|
||||
S("mirror what?", "co odbić?")
|
||||
S("Which orb to use?", "Której Sfery użyć?")
|
||||
S("Unlocked by: %1 in %2", "Odblokwane przez: %1 %abl2")
|
||||
S("Unlocked by: %1 in %2", "Odblokowane przez: %1 %abl2")
|
||||
S(" (next at %1)", " (kolejny przy %1)")
|
||||
S(" (next at %1 to %2)", " (kolejny przy %1 do %2)")
|
||||
S("Number of uses left: %1", "Pozostało użyć: %1")
|
||||
@ -5460,4 +5472,223 @@ S("You mirror %the1.", "Odbijasz %a1.")
|
||||
S("You need to stand next to a magic mirror or cloud to use %the1.",
|
||||
"Musisz stać przy magicznym lustrze, by odbić %a1.")
|
||||
S("Each orb type can be mirrored only once.", "Każdy typ sfery może być odbity tylko raz.")
|
||||
*/
|
||||
|
||||
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\nW trybie strategii sfer Sfery Yendoru się pojawiają w Piekle "
|
||||
"po zebraniu 25 Czarcich Ziel, na Skrzyżowaniu/Oceanie po zebraniu 50, "
|
||||
"wszędzie po zebraniu 100."
|
||||
);
|
||||
|
||||
S(
|
||||
"\n\nIn the Orb Strategy Mode, dead orbs are available once you collect "
|
||||
"10 Necromancer Totems in the Graveyard.",
|
||||
|
||||
"\n\nW trybie strategii sfer martwe sfery są dostępne po zdobyciu "
|
||||
"10 Totemów Nekromanty na Cmentarzu.")
|
||||
|
||||
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\nW trybie strategii sfer Sfery Bezpieczeństwa mogą być zdobyte "
|
||||
"przez zbieranie Piór Feniksa w Krainie Wiecznego Ruchu. "
|
||||
"Można też znaleźć nieograniczone Sfery Bezpieczeństwa na "
|
||||
"Skrzyżowaniach (po zdobyciu 25 Piór Feniksa) i na Prerii."
|
||||
)
|
||||
|
||||
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\nZdobądź %a1 by dostać dodatkową Sferę Lustra. "
|
||||
"Więcej Sfer Lustra dostaniesz przy 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\nW trybie strategii sfer Sfera Szczęścia dodatkowo "
|
||||
"znacznie zwiększa częstotliwość wielkich ścian, Skrzyżowań IV, "
|
||||
"i podkrain.")
|
||||
|
||||
S("\n\nIn the Orb Strategy Mode, each 25 Necromancer's Totems "
|
||||
"you are given a random offensive Orb.",
|
||||
|
||||
"\n\nW trybie strategii sfer każde 25 Totemów Nekromanty "
|
||||
"daje dodatkową ofensywną sferę.")
|
||||
|
||||
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.",
|
||||
|
||||
"Użyj Sfery Lustra by skopiować jedną z Twoich sfer; "
|
||||
"odbijanie słabszych Sfer zwykle daje więcej kopii. "
|
||||
"Możesz użyć tylko raz na każdy typ Sfery, "
|
||||
"i tylko stojąc obok lustra.")
|
||||
|
||||
S("Uses to gain: %1", "Dostaniesz użyć: %1")
|
||||
S("already mirrored", "już było odbijane")
|
||||
|
||||
N("your orbs", GEN_F, "Twoje Sfery", "Twoje Sfery", "Twoje Sfery", "Twoje Sfery")
|
||||
S("Click this to see your orbs.", "Kliknij by zobaczyć Twoje sfery.")
|
||||
|
||||
// peaceful mode
|
||||
S("configure keys/joysticks", "konfiguracja klawiszy/joysticka")
|
||||
S("peaceful mode", "tryb spokojny")
|
||||
|
||||
// config changes
|
||||
S("Press F5 or 'o' to try again!", "Naciśnij F5 lub 'o' by spróbować jeszcze raz!")
|
||||
S("aura brightness", "jasność aury")
|
||||
S("aura smoothening factor", "wygładzanie aury")
|
||||
S("graphics configuration", "konfiguracja grafiki")
|
||||
S("special display modes", "specjalne tryby ekranu")
|
||||
S("openGL mode", "tryb OpenGL")
|
||||
S("anti-aliasing", "anti-aliasing")
|
||||
S("line width", "szerokość linii")
|
||||
S("configure panning and general keys", "skonfiguruj klawisze ogólne")
|
||||
|
||||
S("\n\nHint: use 'm' to toggle cells quickly",
|
||||
"\n\nWsk: użyj 'm' by szybko przestawiać pola");
|
||||
|
||||
// cell pattern names
|
||||
S("football", "piłka nożna")
|
||||
S("dark rainbow landscape", "ciemna tęcza")
|
||||
S("field pattern", "wzór pola")
|
||||
S("field pattern C", "wzór pola C")
|
||||
S("field pattern D", "wzór pola D")
|
||||
S("field pattern N", "wzór pola N")
|
||||
S("field pattern S", "wzór pola S")
|
||||
S("four triangles", "cztery trójkąty")
|
||||
S("big triangles: rings", "duże trójkąty: pierścenie")
|
||||
|
||||
// missing for the Tutorial
|
||||
S("tutorial", "podręcznik")
|
||||
S("This Orb is not compatible with the Tutorial.", "Ta Sfera nie jest kompatybilna z podręcznikiem.")
|
||||
|
||||
// local scores
|
||||
S("turns", "kol")
|
||||
S("cells", "pola")
|
||||
S("sort", "sortuj")
|
||||
S("choose", "wybór")
|
||||
S("play", "graj")
|
||||
|
||||
// draw editor
|
||||
S("autochoose", "autowybór")
|
||||
S("c = choose", "c = wybór")
|
||||
S("b = switch auto", "b = ustaw auto")
|
||||
|
||||
// mission screen hints
|
||||
|
||||
S(
|
||||
"If you collect too many treasures in a given land, it will become "
|
||||
"extremely dangerous. Try other lands once you have enough!",
|
||||
"Jeśli zbierzesz za dużo skarbów w jednej krainie, stanie się ona "
|
||||
"bardzo niebezpieczna. Spróbuj pójść do innych krain, gdy masz dość!");
|
||||
|
||||
S(
|
||||
"Remember that you can right click mostly anything for more information.",
|
||||
"Pamiętaj, że prawie wszystko możesz kliknąć prawym przyciskiem, "
|
||||
"by dowiedzieć się czegoś na dany temat.")
|
||||
|
||||
S("Want to understand the geometry in HyperRogue? Try the Tutorial!",
|
||||
"Chcesz zrozumieć geometrię w HyperRogue? Obejrzyj Podręcznik!");
|
||||
|
||||
S(
|
||||
"Collecting 25 treasures in a given land may be dangerous, "
|
||||
"but allows magical Orbs of this land to appear in other places!",
|
||||
"Zebranie 25 skarbów w jednej krainie może być niebezpieczne, "
|
||||
"ale powoduje, że magiczne Sfery z tej krainy "
|
||||
"pojawiają się w pozostałych krainach!")
|
||||
|
||||
S(
|
||||
"Press ESC to view this screen during the game.",
|
||||
"Naciśnij ESC w czasie gry, by obejrzeć ten ekran.")
|
||||
|
||||
S("The 'world overview' shows all the lands in HyperRogue.",
|
||||
"'Przegląd krain' pokazuje wszystkie krainy w HyperRogue."
|
||||
)
|
||||
|
||||
S("Press 'o' to see all the lands in HyperRogue.",
|
||||
"Naciśnij 'o', by zobaczyć wszystkie krainy w 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!",
|
||||
|
||||
"Chcesz spróbować innego typu gry? Dodatkowych wyzwań?\n"
|
||||
"HyperRogue ma dużo specjalnych trybów, istotnie "
|
||||
"zmieniających styl gry. Wypróbuj je!")
|
||||
|
||||
S(
|
||||
"Hyperbolic geometry can be shown in many ways.",
|
||||
"Geometria hiperboliczna może być pokazana na wiele sposobów...")
|
||||
|
||||
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!",
|
||||
|
||||
"Nie chcesz ginąć od jednego błędu? Chcesz używać Sfer strategicznie? "
|
||||
"Wypróbuj tryb strategii sfer!")
|
||||
|
||||
S(
|
||||
"Do you think you are playing on a ball? "
|
||||
"This is far from the truth!\n",
|
||||
|
||||
"Myślisz, że grasz na sferze? Jest to dalekie od prawdy!\n")
|
||||
|
||||
S(
|
||||
"Did you know that the path you take during the game "
|
||||
"is usually very close to a straight line?\n",
|
||||
|
||||
"Czy wiesz, że droga, którą przebywasz w czasie gry, "
|
||||
"jest zwykle bardzo zbliżona do linii prostej?")
|
||||
|
||||
S("Show me!", "Pokaż!")
|
||||
|
||||
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",
|
||||
|
||||
"Jesteś %1 kroków od punktu startu, lub miejsca "
|
||||
"ostatniego użycia Sfery Bezpieczeństwa. "
|
||||
"Takich pól jest %2.\n")
|
||||
|
||||
S("about ", "około ")
|
||||
S(" (%1 more digits)", " (jeszcze cyfr: %1)")
|
||||
|
||||
S("see how it ended", "jak się skończyło")
|
||||
|
||||
// other missing/new things
|
||||
S("\n\nOrb unlocked: %1", "\n\nOdblokowana Sfera: %1")
|
||||
S("Orb unlocked: %1", "Odblokowana Sfera: %1")
|
||||
S("\n\nSecondary orb: %1", "\n\nDodatkowa Sfera: %1")
|
||||
S(" to submerge", " do zanurzenia")
|
||||
S(" to surface", " do wynurzenia")
|
||||
S("%The1 says, \"not this place, it looks even worse...\"",
|
||||
"%The1 mówi, \"nie tu, tu jest jeszcze gorzej...\"")
|
||||
S("torus", "torus")
|
||||
S(" (click to use)", " (klik by użyć)")
|
||||
N("Hall of Mirrors", GEN_F, "Lustrzana Sala", "Lustrzane Sale", "Lustzaną Salę", "w Lustrzanej Sali")
|
||||
Orb("the Mirror", "Lustra")
|
||||
N("Reflection", GEN_N, "Odbicie", "Odbicia", "Odbicie", "w Odbiciu")
|
||||
N("mirror wall", GEN_F, "lustrzana ściana", "lustrzane ściany", "lustrzaną ścianę", "lustrzaną ścianą")
|
||||
|
||||
S("This would only move you deeper into the trap!",
|
||||
"To tylko przeniesie Cię w głąb pułapki!");
|
||||
|
||||
#undef Orb
|
||||
|
||||
|
@ -1150,7 +1150,7 @@ namespace mapeditor {
|
||||
else if(uni == 'p') {
|
||||
painttype = 6;
|
||||
paintwhat_str = "paint";
|
||||
dialog::openColorDialog(paintwhat = (painttype ==6 ? paintwhat : 0x808080));
|
||||
dialog::openColorDialog((unsigned&)(paintwhat = (painttype ==6 ? paintwhat : 0x808080)));
|
||||
}
|
||||
else if(sym == SDLK_F2) {
|
||||
if(mapstream::saveMap(levelfile.c_str()))
|
||||
@ -1219,7 +1219,7 @@ namespace mapeditor {
|
||||
|
||||
int dslayer;
|
||||
bool coloring;
|
||||
int colortouse = 0xC0C0C0FF;
|
||||
unsigned int colortouse = 0xC0C0C0FFu;
|
||||
|
||||
transmatrix drawtrans, drawtransnew;
|
||||
|
||||
@ -1280,6 +1280,7 @@ namespace mapeditor {
|
||||
|
||||
void showDrawEditor() {
|
||||
cmode = sm::DRAW;
|
||||
gamescreen(0);
|
||||
drawGrid();
|
||||
|
||||
if(!mouseout()) getcstat = '-';
|
||||
@ -1882,7 +1883,7 @@ namespace mapeditor {
|
||||
}
|
||||
|
||||
#ifndef NOEDIT
|
||||
if((cmode == sm::DRAW) && mapeditor::editingShape(group, id)) {
|
||||
if((cmode & sm::DRAW) && mapeditor::editingShape(group, id)) {
|
||||
|
||||
/* for(int a=0; a<size(ds.list); a++) {
|
||||
hyperpoint P2 = V * ds.list[a];
|
||||
@ -1913,6 +1914,8 @@ namespace mapeditor {
|
||||
queuechr(P2, 10, 'x', 0xFF00FF);
|
||||
}
|
||||
|
||||
if(size(ds.list) == 0) return us;
|
||||
|
||||
hyperpoint Plast = V * spin(-2*M_PI/ds.rots) * (ds.sym?Mirror*ds.list[0]:ds.list[size(ds.list)-1]);
|
||||
int state = 0;
|
||||
int gstate = 0;
|
||||
@ -2004,27 +2007,27 @@ namespace linepatterns {
|
||||
struct {
|
||||
int id;
|
||||
const char *lpname;
|
||||
int color;
|
||||
unsigned int color;
|
||||
} patterns[] = {
|
||||
|
||||
{patTriNet, "triangle grid: not rings", (int) 0xFFFFFF00},
|
||||
{patTriRings, "triangle grid: rings", (int) 0xFFFFFF00},
|
||||
{patHepta, "heptagonal grid", (int) 0x0000C000},
|
||||
{patRhomb, "rhombic tesselation", (int) 0x0000C000},
|
||||
{patTrihepta, "triheptagonal tesselation", (int) 0x0000C000},
|
||||
{patNormal, "normal tesselation", (int) 0x0000C000},
|
||||
{patBigTriangles, "big triangular grid", (int) 0x00606000},
|
||||
{patBigRings, "big triangles: rings", (int) 0x0000C000},
|
||||
{patTriNet, "triangle grid: not rings", 0xFFFFFF00},
|
||||
{patTriRings, "triangle grid: rings", 0xFFFFFF00},
|
||||
{patHepta, "heptagonal grid", 0x0000C000},
|
||||
{patRhomb, "rhombic tesselation", 0x0000C000},
|
||||
{patTrihepta, "triheptagonal tesselation", 0x0000C000},
|
||||
{patNormal, "normal tesselation", 0x0000C000},
|
||||
{patBigTriangles, "big triangular grid", 0x00606000},
|
||||
{patBigRings, "big triangles: rings", 0x0000C000},
|
||||
|
||||
{patTree, "underlying tree", (int) 0x00d0d000},
|
||||
{patAltTree, "circle/horocycle tree", (int) 0xd000d000},
|
||||
{patTree, "underlying tree", 0x00d0d000},
|
||||
{patAltTree, "circle/horocycle tree", 0xd000d000},
|
||||
|
||||
{patZebraTriangles, "zebra triangles", (int) 0x40FF4000},
|
||||
{patZebraLines, "zebra lines", (int) 0xFF000000},
|
||||
{patVine, "vineyard pattern", (int) 0x8438A400},
|
||||
{patPalacelike, "firewall lines", (int) 0xFF400000},
|
||||
{patPalace, "firewall lines: Palace", (int) 0xFFD50000},
|
||||
{patPower, "firewall lines: Power", (int) 0xFFFF0000},
|
||||
{patZebraTriangles, "zebra triangles", 0x40FF4000},
|
||||
{patZebraLines, "zebra lines", 0xFF000000},
|
||||
{patVine, "vineyard pattern", 0x8438A400},
|
||||
{patPalacelike, "firewall lines", 0xFF400000},
|
||||
{patPalace, "firewall lines: Palace", 0xFFD50000},
|
||||
{patPower, "firewall lines: Power", 0xFFFF0000},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -401,7 +401,7 @@ void showChangeMode() {
|
||||
dialog::addBoolItem(XLAT("heptagonal mode"), (purehepta), '7');
|
||||
dialog::addBoolItem(XLAT("Chaos mode"), (chaosmode), 'C');
|
||||
dialog::addBoolItem(XLAT("peaceful mode"), (chaosmode), 'p');
|
||||
dialog::addBoolItem(XLAT("inventory mode"), (inv::on), 'i');
|
||||
dialog::addBoolItem(XLAT("Orb Strategy mode"), (inv::on), 'i');
|
||||
dialog::addBoolItem(XLAT("pure tactics mode"), (tactic::on), 't');
|
||||
dialog::addBoolItem(XLAT("Yendor Challenge"), (yendor::on), 'y');
|
||||
dialog::addBoolItem(XLAT("%1 Challenge", moPrincess), (princess::challenge), 'P');
|
||||
|
77
orbs.cpp
77
orbs.cpp
@ -343,6 +343,7 @@ void castLightningBolt(cellwalker lig) {
|
||||
if(lig.c->mov[lig.spin] == NULL) break;
|
||||
|
||||
cwstep(lig);
|
||||
if(inmirror(lig)) lig = mirror::reflect(lig);
|
||||
|
||||
cell *c = lig.c;
|
||||
|
||||
@ -1188,3 +1189,79 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
return eItem(-1);
|
||||
}
|
||||
|
||||
int orbcharges(eItem it) {
|
||||
switch(it) {
|
||||
case itRevolver: //pickup-key
|
||||
return 6;
|
||||
case itOrbShield:
|
||||
return inv::on ? 30 : 20;
|
||||
case itOrbDiscord:
|
||||
return inv::on ? 46 : 23;
|
||||
case itOrbLove:
|
||||
case itOrbUndeath:
|
||||
case itOrbSpeed: //"pickup-speed");
|
||||
case itOrbInvis:
|
||||
case itOrbAether:
|
||||
return 30;
|
||||
case itOrbWinter: // "pickup-winter"
|
||||
return inv::on ? 45 : 30;
|
||||
break;
|
||||
case itOrbBeauty:
|
||||
case itOrbEmpathy:
|
||||
case itOrbFreedom:
|
||||
return 40;
|
||||
case itOrbFrog:
|
||||
case itOrbDash:
|
||||
return 45;
|
||||
case itOrb37:
|
||||
case itOrbEnergy:
|
||||
return 50;
|
||||
case itOrbRecall:
|
||||
case itOrbNature:
|
||||
case itOrbStone:
|
||||
case itOrbStunning:
|
||||
case itOrbLuck:
|
||||
return 60;
|
||||
case itOrbWater:
|
||||
case itOrbMatter:
|
||||
case itOrbHorns:
|
||||
case itOrbBull:
|
||||
case itOrbShell:
|
||||
return 66;
|
||||
case itOrbTime:
|
||||
case itOrbSpace:
|
||||
case itOrbThorns:
|
||||
case itOrbLightning:
|
||||
case itOrbFlash:
|
||||
case itOrbIllusion:
|
||||
case itOrbPsi:
|
||||
case itOrbDigging:
|
||||
case itOrbTeleport:
|
||||
return 77;
|
||||
case itOrbDomination:
|
||||
return 90;
|
||||
case itOrbSummon:
|
||||
return 120;
|
||||
|
||||
case itOrbSword:
|
||||
return 60 + 30 * multi::activePlayers();
|
||||
case itOrbSword2:
|
||||
return 40 + 20 * multi::activePlayers();
|
||||
case itOrbFish:
|
||||
return 20 + 10 * multi::activePlayers();
|
||||
case itOrbFire:
|
||||
return sphere ? 3 : 30;
|
||||
case itOrbDragon:
|
||||
return sphere ? 10 : 77;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool isShmupLifeOrb(eItem it) {
|
||||
return
|
||||
it == itOrbLife || it == itOrbFriend ||
|
||||
it == itOrbNature || it == itOrbEmpathy ||
|
||||
it == itOrbUndeath || it == itOrbLove ||
|
||||
it == itOrbDomination;
|
||||
}
|
||||
|
58
polygons.cpp
58
polygons.cpp
@ -630,10 +630,11 @@ hpcshape
|
||||
shBarrowFloor[3],
|
||||
shTriheptaFloor[11], shTriheptaFloor2[2], shTriheptaEuc[3],
|
||||
shCross, shGiantStar[2], shLake, shMirror,
|
||||
shHalfFloor[3], shHalfMirror[3],
|
||||
shGem[2], shStar, shDisk, shDiskT, shDiskS, shDiskM, shDiskSq, shRing,
|
||||
shEgg,
|
||||
shSpikedRing, shTargetRing, shSawRing, shGearRing, shPeaceRing, shHeptaRing,
|
||||
shSpearRing,
|
||||
shSpearRing, shLoveRing,
|
||||
shDaisy, shTriangle, shNecro, shStatue, shKey,
|
||||
shGun,
|
||||
shFigurine, shTreat,
|
||||
@ -1112,6 +1113,36 @@ void buildpolys() {
|
||||
}
|
||||
hpcpush(ddi(0, crossf * .25) * C0);
|
||||
|
||||
/* three nice spikes
|
||||
bshape(shLoveRing, PPR_ITEM);
|
||||
for(int i=0; i<=S84; i+=3)
|
||||
hpcpush(ddi(i, crossf * .25) * C0);
|
||||
for(int i=S84; i>=0; i--) {
|
||||
int j = i*3 % S84;
|
||||
int d = j - S42;
|
||||
if(d<0) d = -d;
|
||||
d = 8 - 2 * d;
|
||||
if(d<0) d = 0;
|
||||
hpcpush(ddi(i, crossf * (.3 + .02 * d)) * C0);
|
||||
}
|
||||
hpcpush(ddi(0, crossf * .25) * C0);
|
||||
*/
|
||||
|
||||
bshape(shLoveRing, PPR_ITEM);
|
||||
for(int i=0; i<=S84; i+=3)
|
||||
hpcpush(ddi(i, crossf * .25) * C0);
|
||||
for(int i=S84; i>=0; i--) {
|
||||
int j = i*3 % S84;
|
||||
double d = j - S42;
|
||||
d = d / 9;
|
||||
if(d<0) d = -d;
|
||||
d = 8 - 2 * d;
|
||||
if(d<0) d = 0;
|
||||
if(d >= 6) d -= (d-6)/3;
|
||||
hpcpush(ddi(i, crossf * (.27 + .02 * d)) * C0);
|
||||
}
|
||||
hpcpush(ddi(0, crossf * .25) * C0);
|
||||
|
||||
bshape(shSawRing, PPR_ITEM);
|
||||
for(int i=0; i<=S84; i+=3)
|
||||
hpcpush(ddi(i, crossf * .25) * C0);
|
||||
@ -1242,6 +1273,13 @@ void buildpolys() {
|
||||
bshape(shButterflyFloor[0], PPR_FLOOR, scalef*spzoom6, 325);
|
||||
bshape(shButterflyFloor[1], PPR_FLOOR, scalef*spzoomd7, 326);
|
||||
|
||||
bshape(shHalfFloor[0], PPR_FLOOR, scalef*spzoom6, 329);
|
||||
bshape(shHalfFloor[1], PPR_FLOOR, scalef*spzoom6, 327);
|
||||
bshape(shHalfFloor[2], PPR_FLOOR, scalef*spzoom6, 331);
|
||||
bshape(shHalfMirror[0], PPR_WALL, scalef*spzoom6, 330);
|
||||
bshape(shHalfMirror[1], PPR_WALL, scalef*spzoom6, 328);
|
||||
bshape(shHalfMirror[2], PPR_WALL, scalef*spzoom6, 332);
|
||||
|
||||
bshape(shLeafFloor[0], PPR_FLOOR_DRAGON, 1*spzoom6, 313);
|
||||
bshape(shLeafFloor[1], PPR_FLOOR_DRAGON, 1*spzoomd7, 314);
|
||||
|
||||
@ -2009,6 +2047,10 @@ void queuecircle(const transmatrix& V, double size, int col) {
|
||||
queuecircle(xc, yc, int(sqrt(squar(xc-xs)+squar(yc-ys)) * size), col);
|
||||
}
|
||||
|
||||
void queuemarkerat(const transmatrix& V, int col) {
|
||||
queuepolyat(V, shTriangle, col, PPR_LINE);
|
||||
}
|
||||
|
||||
long double polydata[] = {
|
||||
// shStarFloor[0] (6x1)
|
||||
NEWSHAPE, 1,6,1, 0.267355,0.153145, 0.158858,0.062321, 0.357493,-0.060252,
|
||||
@ -2660,6 +2702,20 @@ NEWSHAPE, 325, 3, 1, 0.003906,-0.017741, -0.005665,-0.023874, -0.001296,-0.05925
|
||||
// shButterflyFloor[1]
|
||||
NEWSHAPE, 326, 7, 1, -0.199281,-0.117040, -0.202870,-0.110023, -0.247957,-0.128116, -0.298501,0.006170, -0.226086,0.045756, -0.061553,0.006677, -0.059070,0.020733, -0.217691,0.072727,
|
||||
|
||||
// halfhepta
|
||||
NEWSHAPE, 327, 1, 1, 0.335252,0.044112, 0.225849,0.283419, -0.081851,0.347313, -0.325491,0.159424, -0.323584,0.033019,
|
||||
// hepta mirror
|
||||
NEWSHAPE, 328, 1, 2, -0.315398,0.010102, 0.568278,0.010645,
|
||||
|
||||
// halfhex
|
||||
NEWSHAPE, 329, 1, 1, 0.263160,0.022375, 0.265137,0.152727, 0.000228,0.306625, -0.261438,0.151819, -0.263489,0.020161,
|
||||
// halfhex mirror
|
||||
NEWSHAPE, 330, 1, 2, 0.262597,0.018558, -0.261563,0.016306,
|
||||
|
||||
NEWSHAPE, 331, 1, 1, 0.148337,0.215535, 0.267624,0.150567, 0.262973,0.019662, 0.033981,0.019835,
|
||||
// 0 0 1 [000000]
|
||||
NEWSHAPE, 332, 6, 2, -0.016778,-0.008267, -0.261607,-0.011992,
|
||||
|
||||
NEWSHAPE
|
||||
};
|
||||
|
||||
|
31
quit.cpp
31
quit.cpp
@ -19,13 +19,6 @@ string timeline() {
|
||||
XLAT("%1 turns (%2)", its(turncount), buf);
|
||||
}
|
||||
|
||||
struct hint {
|
||||
time_t last;
|
||||
function<bool()> usable;
|
||||
function<void()> display;
|
||||
function<void()> action;
|
||||
};
|
||||
|
||||
void noaction() {}
|
||||
|
||||
function<void()> cancel = noaction;
|
||||
@ -58,7 +51,7 @@ hint hints[] = {
|
||||
},
|
||||
[]() {
|
||||
dialog::addHelp(XLAT(
|
||||
"If you collect too many treasures in a given land, monsters will be "
|
||||
"If you collect too many treasures in a given land, it will become "
|
||||
"extremely dangerous. Try other lands once you have enough!"));
|
||||
},
|
||||
noaction},
|
||||
@ -97,7 +90,7 @@ hint hints[] = {
|
||||
[]() { return !inv::on; },
|
||||
[]() {
|
||||
dialog::addHelp(XLAT(
|
||||
"Collecting 25 treasures in a given land is dangerous, "
|
||||
"Collecting 25 treasures in a given land may be dangerous, "
|
||||
"but allows magical Orbs of this land to appear in other places!"
|
||||
));
|
||||
},
|
||||
@ -136,7 +129,7 @@ hint hints[] = {
|
||||
0,
|
||||
[]() { return !canmove; },
|
||||
[]() {
|
||||
dialog::addInfo(XLAT(
|
||||
dialog::addHelp(XLAT(
|
||||
"Want another type of game? Want more challenge?\n"
|
||||
"HyperRogue has many special modes and challenges that "
|
||||
"significantly change the gameplay. Try them!"
|
||||
@ -174,8 +167,6 @@ hint hints[] = {
|
||||
dialog::addBreak(50);
|
||||
#ifdef INF
|
||||
dialog::addItem(XLAT("Orb Strategy mode"), 'z');
|
||||
#else
|
||||
dialog::addItem(XLAT("(paid versions only)"), 'z');
|
||||
#endif
|
||||
},
|
||||
[]() {
|
||||
@ -193,7 +184,7 @@ hint hints[] = {
|
||||
"This is far from the truth!\n"
|
||||
));
|
||||
dialog::addBreak(50);
|
||||
dialog::addItem(XLAT("Hypersian Rug mode"), 'z');
|
||||
dialog::addItem(XLAT("hypersian rug mode"), 'z');
|
||||
},
|
||||
[] () {
|
||||
popScreen();
|
||||
@ -217,7 +208,7 @@ hint hints[] = {
|
||||
[]() {
|
||||
dialog::addHelp(XLAT(
|
||||
"Did you know that the path you take during the game "
|
||||
"is very close to a straight line?\n"
|
||||
"is usually very close to a straight line?\n"
|
||||
));
|
||||
dialog::addBreak(50);
|
||||
dialog::addItem(XLAT("Show me!"), 'z');
|
||||
@ -299,6 +290,10 @@ hint hints[] = {
|
||||
|
||||
int hinttoshow;
|
||||
|
||||
string contstr() {
|
||||
return XLAT(canmove ? "continue" : "see how it ended");
|
||||
}
|
||||
|
||||
void showMission() {
|
||||
|
||||
cmode = sm::DOTOUR | sm::MISSION | sm::CENTER;
|
||||
@ -439,9 +434,11 @@ void showMission() {
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
dialog::addItem(XLAT(canmove ? "continue" : "see how it ended"), SDLK_ESCAPE);
|
||||
dialog::addItem(contstr(), SDLK_ESCAPE);
|
||||
dialog::addItem(XLAT("main menu"), 'v');
|
||||
dialog::addItem(XLAT("restart"), SDLK_F5);
|
||||
if(inv::on && items[itInventory])
|
||||
dialog::addItem(XLAT("inventory"), 'i');
|
||||
#ifndef MOBILE
|
||||
dialog::addItem(XLAT(quitsaves() ? "save" : "quit"), SDLK_F10);
|
||||
#endif
|
||||
@ -469,7 +466,7 @@ void handleKeyQuit(int sym, int uni) {
|
||||
|
||||
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER || sym == SDLK_F10) quitmainloop = true;
|
||||
else if(uni == 'r' || sym == SDLK_F5) {
|
||||
restartGame(), popScreen();
|
||||
restartGame();
|
||||
msgs.clear();
|
||||
}
|
||||
else if(sym == SDLK_UP || sym == SDLK_KP8 || sym == PSEUDOKEY_WHEELUP) msgscroll++;
|
||||
@ -524,5 +521,7 @@ void showMissionScreen() {
|
||||
}
|
||||
hints[hinttoshow].last = time(NULL);
|
||||
}
|
||||
|
||||
dialog::highlight_text = contstr();
|
||||
}
|
||||
|
||||
|
2
rug.cpp
2
rug.cpp
@ -42,7 +42,7 @@ bool glew = false;
|
||||
bool renderonce = false;
|
||||
bool rendernogl = false;
|
||||
int texturesize = 1024;
|
||||
double scale = 1;
|
||||
ld scale = 1;
|
||||
|
||||
int queueiter, qvalid, dt;
|
||||
double err;
|
||||
|
@ -39,6 +39,7 @@ bool isHardcore(score *S) {
|
||||
int modediff(score *S) {
|
||||
int diff = 0;
|
||||
eGeometry g = (eGeometry) S->box[116];
|
||||
if(S->box[306] != inv::on) diff += 4;
|
||||
if(S->box[238]) g = gSphere;
|
||||
if(S->box[239]) g = gElliptic;
|
||||
if(max(S->box[197], 1) != multi::players) diff += 8;
|
||||
@ -64,6 +65,7 @@ string modedesc(score *S) {
|
||||
if(S->box[196]) s += "/C";
|
||||
if(S->box[119]) s += "/s";
|
||||
if(S->box[197] > 1) s += "/P" + its(S->box[197]);
|
||||
if(S->box[306]) s += "/i";
|
||||
if(isHardcore(S)) s += "/h";
|
||||
return s;
|
||||
}
|
||||
@ -301,7 +303,7 @@ void load() {
|
||||
|
||||
for(int i=boxid; i<MAXBOX; i++) sc.box[i] = 0;
|
||||
|
||||
if(sc.ver >= "4.4") {
|
||||
if(!verless(sc.ver, "4.4")) {
|
||||
sc.box[0] = sc.box[65];
|
||||
// the first executable on Steam included a corruption
|
||||
if(sc.box[65] > 1420000000 && sc.box[65] < 1430000000) {
|
||||
|
233
shmup.cpp
233
shmup.cpp
@ -60,6 +60,9 @@ namespace multi {
|
||||
movedir whereto[MAXPLAYER]; // player's target cell
|
||||
|
||||
double mdx[MAXPLAYER], mdy[MAXPLAYER]; // movement vector for the next move
|
||||
|
||||
static const int CMDS = 15;
|
||||
static const int CMDS_PAN = 11;
|
||||
|
||||
const char* playercmds_shmup[15] = {
|
||||
"forward", "backward", "turn left", "turn right",
|
||||
@ -77,13 +80,15 @@ namespace multi {
|
||||
""
|
||||
};
|
||||
|
||||
const char* pancmds[7] = {
|
||||
const char* pancmds[11] = {
|
||||
"pan up", "pan right", "pan down", "pan left",
|
||||
"rotate left", "rotate right", "home"
|
||||
"rotate left", "rotate right", "home",
|
||||
"world overview", "review your quest", "inventory", "main menu"
|
||||
};
|
||||
|
||||
#define SHMUPAXES_BASE 4
|
||||
#define SHMUPAXES ((SHMUPAXES_BASE) + 4 * (MAXPLAYER))
|
||||
#define SHMUPAXES_CUR ((SHMUPAXES_BASE) + 4 * vid.scfg.players)
|
||||
|
||||
const char* axemodes[SHMUPAXES] = {
|
||||
"do nothing",
|
||||
@ -122,44 +127,6 @@ const char* axemodes[SHMUPAXES] = {
|
||||
|
||||
int centerplayer = -1;
|
||||
|
||||
#ifndef NOCONFIG
|
||||
void saveConfig(FILE *f) {
|
||||
fprintf(f, "%d %d %d", VERNUM, vid.scfg.players, alwaysuse);
|
||||
for(int i=0; i<512; i++) fprintf(f, " %d", vid.scfg.keyaction[i]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXBUTTON; j++) fprintf(f, " %d", vid.scfg.joyaction[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXAXE; j++) fprintf(f, " %d", vid.scfg.axeaction[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXAXE; j++) fprintf(f, " %d", vid.scfg.deadzoneval[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXHAT; j++) for(int k=0; k<4; k++)
|
||||
fprintf(f, " %d", vid.scfg.hataction[i][j][k]);
|
||||
fprintf(f, "\n");
|
||||
for(int i=0; i<MAXPLAYER; i++) savecs(f, scs[i], VERNUM);
|
||||
}
|
||||
|
||||
void scanchar(FILE *f, char& c) {
|
||||
int i = c;
|
||||
int err = fscanf(f, "%d", &i);
|
||||
if(err == 1) c = i;
|
||||
}
|
||||
|
||||
void loadConfig(FILE *f) {
|
||||
int xvernum;
|
||||
int err = fscanf(f, "%d %d", &xvernum, &vid.scfg.players);
|
||||
if(vid.scfg.players < 1 || vid.scfg.players > MAXPLAYER)
|
||||
vid.scfg.players = 1;
|
||||
if(err != 2) return;
|
||||
if(xvernum >= 8990) { int b=alwaysuse; err=fscanf(f, " %d", &b); alwaysuse = b; }
|
||||
for(int i=0; i<512; i++) scanchar(f, vid.scfg.keyaction[i]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXBUTTON; j++) scanchar(f, vid.scfg.joyaction[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXAXE; j++) scanchar(f, vid.scfg.axeaction[i][j]);
|
||||
|
||||
if(xvernum >= 9007)
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXAXE; j++) err = fscanf(f, " %d", &vid.scfg.deadzoneval[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXHAT; j++) for(int k=0; k<4; k++)
|
||||
scanchar(f, vid.scfg.hataction[i][j][k]);
|
||||
for(int i=0; i<(xvernum < 8990 ? 4 : 7); i++) loadcs(f, scs[i], xvernum);
|
||||
}
|
||||
#endif
|
||||
|
||||
int shmupnumkeys;
|
||||
const char** shmupcmdtable;
|
||||
|
||||
@ -213,15 +180,16 @@ void handleConfig(int sym, int uni);
|
||||
|
||||
void showShmupConfig() {
|
||||
#ifndef NOSDL
|
||||
cmode = sm::SHMUPCONFIG;
|
||||
|
||||
int sc = vid.scfg.subconfig;
|
||||
|
||||
if(sc == 1 || sc == 2 || sc == 4 || sc == 5 || sc == 6 || sc == 7 || sc == 8) {
|
||||
shmupnumkeys = 15;
|
||||
shmupnumkeys = CMDS;
|
||||
shmupcmdtable = shmup::on ? playercmds_shmup : playercmds_turn;
|
||||
}
|
||||
else if(sc == 3) {
|
||||
shmupnumkeys = 7;
|
||||
shmupnumkeys = CMDS_PAN;
|
||||
shmupcmdtable = pancmds;
|
||||
}
|
||||
else if(sc == SCJOY) {
|
||||
@ -304,7 +272,7 @@ void showShmupConfig() {
|
||||
else dialog::addBreak(100);
|
||||
|
||||
if(shmupcfg || multi::alwaysuse || vid.scfg.players > 1)
|
||||
dialog::addItem(XLAT("configure panning"), 'p');
|
||||
dialog::addItem(XLAT("configure panning and general keys"), 'p');
|
||||
else dialog::addBreak(100);
|
||||
|
||||
if(numsticks > 0) {
|
||||
@ -442,8 +410,8 @@ help += XLAT("This menu can be also used to configure keys.\n\n");
|
||||
else {
|
||||
int v = (*axeconfigs[xuni - 'a']);
|
||||
v += (shiftmul>0?1:-1);
|
||||
v += SHMUPAXES;
|
||||
v %= SHMUPAXES;
|
||||
v += SHMUPAXES_CUR;
|
||||
v %= SHMUPAXES_CUR;
|
||||
(*axeconfigs[xuni - 'a']) = v;
|
||||
}
|
||||
}
|
||||
@ -494,63 +462,7 @@ bool notremapped(int sym) {
|
||||
return k > multi::players;
|
||||
}
|
||||
|
||||
void handleInput(int delta) {
|
||||
#ifndef NOSDL
|
||||
double d = delta / 500.;
|
||||
|
||||
Uint8 *keystate = SDL_GetKeyState(NULL);
|
||||
|
||||
for(int i=0; i<NUMACT; i++)
|
||||
lactionpressed[i] = actionspressed[i],
|
||||
actionspressed[i] = 0;
|
||||
|
||||
for(int i=0; i<SHMUPAXES; i++) axespressed[i] = 0;
|
||||
|
||||
for(int i=0; i<SDLK_LAST; i++) if(keystate[i])
|
||||
pressaction(vid.scfg.keyaction[i]);
|
||||
|
||||
for(int j=0; j<numsticks; j++) {
|
||||
|
||||
for(int b=0; b<SDL_JoystickNumButtons(sticks[j]) && b<MAXBUTTON; b++)
|
||||
if(SDL_JoystickGetButton(sticks[j], b))
|
||||
pressaction(vid.scfg.joyaction[j][b]);
|
||||
|
||||
for(int b=0; b<SDL_JoystickNumHats(sticks[j]) && b<MAXHAT; b++) {
|
||||
int stat = SDL_JoystickGetHat(sticks[j], b);
|
||||
if(stat & SDL_HAT_UP) pressaction(vid.scfg.hataction[j][b][0]);
|
||||
if(stat & SDL_HAT_RIGHT) pressaction(vid.scfg.hataction[j][b][1]);
|
||||
if(stat & SDL_HAT_DOWN) pressaction(vid.scfg.hataction[j][b][2]);
|
||||
if(stat & SDL_HAT_LEFT) pressaction(vid.scfg.hataction[j][b][3]);
|
||||
}
|
||||
|
||||
for(int b=0; b<SDL_JoystickNumAxes(sticks[j]) && b<MAXAXE; b++) {
|
||||
int value = SDL_JoystickGetAxis(sticks[j], b);
|
||||
int dz = vid.scfg.deadzoneval[j][b];
|
||||
if(value > dz) value -= dz; else if(value < -dz) value += dz;
|
||||
else value = 0;
|
||||
axespressed[vid.scfg.axeaction[j][b] % SHMUPAXES] += value;
|
||||
}
|
||||
}
|
||||
|
||||
if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5;
|
||||
|
||||
double panx =
|
||||
actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0;
|
||||
double pany =
|
||||
actionspressed[50] - actionspressed[48] + axespressed[3] / 20000.0;
|
||||
|
||||
double panspin = actionspressed[52] - actionspressed[53] + axespressed[1] / 20000.0;
|
||||
|
||||
if(actionspressed[54]) { centerplayer = -1, playermoved = true; centerpc(100); }
|
||||
|
||||
if(panx || pany || panspin) {
|
||||
View = xpush(-panx * d) * ypush(-pany * d) * spin(panspin * d) * View;
|
||||
playermoved = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int tableid[7] = {1, 2, 4, 5, 6, 7, 8};
|
||||
#ifndef NOCONFIG
|
||||
|
||||
void initConfig() {
|
||||
vid.scfg.players = 1;
|
||||
@ -650,8 +562,125 @@ void initConfig() {
|
||||
multi::scs[4].uicolor = 0xC000C0FF;
|
||||
multi::scs[5].uicolor = 0x00C0C0FF;
|
||||
multi::scs[6].uicolor = 0xC0C0C0FF;
|
||||
|
||||
addsaver(vid.scfg.players, "mode-number of players");
|
||||
addsaver(alwaysuse, "use configured keys");
|
||||
// unfortunately we cannot use key names here because SDL is not yet initialized
|
||||
for(int i=0; i<512; i++)
|
||||
addsaver(vid.scfg.keyaction[i], string("key:")+its(i));
|
||||
for(int i=0; i<MAXJOY; i++) {
|
||||
string pre = "joystick "+cts('A'+i);
|
||||
for(int j=0; j<MAXBUTTON; j++)
|
||||
addsaver(vid.scfg.joyaction[i][j], pre+"-B"+its(j));
|
||||
for(int j=0; j<MAXAXE; j++) {
|
||||
addsaver(vid.scfg.axeaction[i][j], pre+" axis "+its(j));
|
||||
addsaver(vid.scfg.deadzoneval[i][j], pre+" deadzone "+its(j));
|
||||
}
|
||||
for(int j=0; j<MAXHAT; j++) for(int k=0; k<4; k++) {
|
||||
addsaver(vid.scfg.hataction[i][j][k], pre+" hat "+its(j)+" "+"URDL"[k]);
|
||||
}
|
||||
}
|
||||
for(int i=0; i<7; i++) addsaver(multi::scs[i], "player"+its(i));
|
||||
}
|
||||
|
||||
void scanchar(FILE *f, char& c) {
|
||||
int i = c;
|
||||
int err = fscanf(f, "%d", &i);
|
||||
if(err == 1) c = i;
|
||||
}
|
||||
|
||||
void loadConfig(FILE *f) {
|
||||
int xvernum;
|
||||
int err = fscanf(f, "%d %d", &xvernum, &vid.scfg.players);
|
||||
if(vid.scfg.players < 1 || vid.scfg.players > MAXPLAYER)
|
||||
vid.scfg.players = 1;
|
||||
if(err != 2) return;
|
||||
if(xvernum >= 8990) { int b=alwaysuse; err=fscanf(f, " %d", &b); alwaysuse = b; }
|
||||
for(int i=0; i<512; i++) scanchar(f, vid.scfg.keyaction[i]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXBUTTON; j++) scanchar(f, vid.scfg.joyaction[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXAXE; j++) scanchar(f, vid.scfg.axeaction[i][j]);
|
||||
|
||||
if(xvernum >= 9007)
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXAXE; j++) err = fscanf(f, " %d", &vid.scfg.deadzoneval[i][j]);
|
||||
for(int i=0; i<MAXJOY; i++) for(int j=0; j<MAXHAT; j++) for(int k=0; k<4; k++)
|
||||
scanchar(f, vid.scfg.hataction[i][j][k]);
|
||||
for(int i=0; i<(xvernum < 8990 ? 4 : 7); i++) loadcs(f, scs[i], xvernum);
|
||||
}
|
||||
#endif
|
||||
|
||||
void handleInput(int delta) {
|
||||
#ifndef NOSDL
|
||||
double d = delta / 500.;
|
||||
|
||||
Uint8 *keystate = SDL_GetKeyState(NULL);
|
||||
|
||||
for(int i=0; i<NUMACT; i++)
|
||||
lactionpressed[i] = actionspressed[i],
|
||||
actionspressed[i] = 0;
|
||||
|
||||
for(int i=0; i<SHMUPAXES; i++) axespressed[i] = 0;
|
||||
|
||||
for(int i=0; i<SDLK_LAST; i++) if(keystate[i])
|
||||
pressaction(vid.scfg.keyaction[i]);
|
||||
|
||||
for(int j=0; j<numsticks; j++) {
|
||||
|
||||
for(int b=0; b<SDL_JoystickNumButtons(sticks[j]) && b<MAXBUTTON; b++)
|
||||
if(SDL_JoystickGetButton(sticks[j], b))
|
||||
pressaction(vid.scfg.joyaction[j][b]);
|
||||
|
||||
for(int b=0; b<SDL_JoystickNumHats(sticks[j]) && b<MAXHAT; b++) {
|
||||
int stat = SDL_JoystickGetHat(sticks[j], b);
|
||||
if(stat & SDL_HAT_UP) pressaction(vid.scfg.hataction[j][b][0]);
|
||||
if(stat & SDL_HAT_RIGHT) pressaction(vid.scfg.hataction[j][b][1]);
|
||||
if(stat & SDL_HAT_DOWN) pressaction(vid.scfg.hataction[j][b][2]);
|
||||
if(stat & SDL_HAT_LEFT) pressaction(vid.scfg.hataction[j][b][3]);
|
||||
}
|
||||
|
||||
for(int b=0; b<SDL_JoystickNumAxes(sticks[j]) && b<MAXAXE; b++) {
|
||||
int value = SDL_JoystickGetAxis(sticks[j], b);
|
||||
int dz = vid.scfg.deadzoneval[j][b];
|
||||
if(value > dz) value -= dz; else if(value < -dz) value += dz;
|
||||
else value = 0;
|
||||
axespressed[vid.scfg.axeaction[j][b] % SHMUPAXES] += value;
|
||||
}
|
||||
}
|
||||
|
||||
if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5;
|
||||
|
||||
double panx =
|
||||
actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0;
|
||||
double pany =
|
||||
actionspressed[50] - actionspressed[48] + axespressed[3] / 20000.0;
|
||||
|
||||
double panspin = actionspressed[52] - actionspressed[53] + axespressed[1] / 20000.0;
|
||||
|
||||
if(actionspressed[54]) { centerplayer = -1, playermoved = true; centerpc(100); }
|
||||
|
||||
if(actionspressed[55] && !lactionpressed[55])
|
||||
pushScreen(showOverview);
|
||||
|
||||
if(actionspressed[56] && !lactionpressed[56])
|
||||
showMissionScreen();
|
||||
|
||||
#ifdef INV
|
||||
if(actionspressed[57] && !lactionpressed[57])
|
||||
pushScreen(inv::show);
|
||||
#endif
|
||||
|
||||
if(actionspressed[58] && !lactionpressed[58])
|
||||
pushScreen(showMainMenu);
|
||||
|
||||
if(panx || pany || panspin) {
|
||||
View = xpush(-panx * d) * ypush(-pany * d) * spin(panspin * d) * View;
|
||||
playermoved = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int tableid[7] = {1, 2, 4, 5, 6, 7, 8};
|
||||
|
||||
|
||||
void leaveGame(int i) {
|
||||
multi::player[i].c = NULL;
|
||||
multi::deaths[i]++;
|
||||
|
148
system.cpp
148
system.cpp
@ -15,6 +15,13 @@ bool timerstopped;
|
||||
int savecount;
|
||||
bool showoff = false, doCross = false;
|
||||
|
||||
bool verless(const string& v, const string& cmp) {
|
||||
// no checks exists for versions greater than 10.0 yet
|
||||
if(isdigit(v[0]) && isdigit(v[1]))
|
||||
return false;
|
||||
return v < cmp;
|
||||
}
|
||||
|
||||
// initialize the game
|
||||
void initgame() {
|
||||
DEBB(DF_INIT, (debugfile,"initGame\n"));
|
||||
@ -167,6 +174,8 @@ void initgame() {
|
||||
makeEmpty(cwt.c);
|
||||
}
|
||||
|
||||
princess::squeaked = false;
|
||||
|
||||
if(!safety) {
|
||||
usedSafety = false;
|
||||
timerstart = time(NULL); turncount = 0; rosewave = 0; rosephase = 0;
|
||||
@ -254,8 +263,8 @@ void initgame() {
|
||||
bool havesave = true;
|
||||
|
||||
#ifndef NOSAVE
|
||||
#define MAXBOX 300
|
||||
#define POSSCORE 258 // update this when new boxes are added!
|
||||
#define MAXBOX 500
|
||||
#define POSSCORE 308 // update this when new boxes are added!
|
||||
|
||||
struct score {
|
||||
string ver;
|
||||
@ -275,7 +284,7 @@ void applyBox(int& t) {
|
||||
else boxid++;
|
||||
}
|
||||
|
||||
void applyBoxNum(int& i, string name = "") {
|
||||
void applyBoxNum(int& i, string name) {
|
||||
fakebox[boxid] = (name == "");
|
||||
boxname[boxid] = name;
|
||||
monsbox[boxid] = false;
|
||||
@ -313,6 +322,31 @@ void applyBoxI(eItem it, bool f = false) {
|
||||
else applyBox(items[it]);
|
||||
}
|
||||
|
||||
vector<eItem> invorb;
|
||||
|
||||
void addinv(eItem it) {
|
||||
invorb.push_back(it);
|
||||
}
|
||||
|
||||
void applyBoxOrb(eItem it) {
|
||||
applyBoxI(it, true);
|
||||
invorb.push_back(it);
|
||||
}
|
||||
|
||||
void list_invorb() {
|
||||
for(eItem it: invorb) {
|
||||
#ifdef INV
|
||||
if(true) {
|
||||
inv::applyBox(it);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
int u = 0;
|
||||
applyBoxNum(u);
|
||||
}
|
||||
invorb.clear();
|
||||
}
|
||||
|
||||
void applyBoxM(eMonster m, bool f = false) {
|
||||
fakebox[boxid] = f;
|
||||
boxname[boxid] = minf[m].name;
|
||||
@ -321,6 +355,7 @@ void applyBoxM(eMonster m, bool f = false) {
|
||||
}
|
||||
|
||||
void applyBoxes() {
|
||||
invorb.clear();
|
||||
|
||||
eLand lostin = laNone;
|
||||
|
||||
@ -347,9 +382,9 @@ void applyBoxes() {
|
||||
else if(i == moWormwait) applyBoxM(moFireFairy);
|
||||
else if(i == moTentacleEscaping) applyBoxM(moMiner);
|
||||
else if(i == moGolemMoved) applyBoxM(moIllusion);
|
||||
else if(i == moTentaclewait) applyBoxI(itOrbThorns, true);
|
||||
else if(i == moGreater) applyBoxI(itOrbDragon, true);
|
||||
else if(i == moGreaterM) applyBoxI(itOrbIllusion, true);
|
||||
else if(i == moTentaclewait) applyBoxOrb(itOrbThorns);
|
||||
else if(i == moGreater) applyBoxOrb(itOrbDragon);
|
||||
else if(i == moGreaterM) applyBoxOrb(itOrbIllusion);
|
||||
else applyBoxM(eMonster(i), fake);
|
||||
}
|
||||
|
||||
@ -371,17 +406,17 @@ void applyBoxes() {
|
||||
else if(loading) firstland = safetyland = eLand(applyBoxLoad());
|
||||
else lostin = eLand(savebox[boxid++]);
|
||||
|
||||
for(int i=itOrbLightning; i<25; i++) applyBoxI(eItem(i), true);
|
||||
for(int i=itOrbLightning; i<25; i++) applyBoxOrb(eItem(i));
|
||||
|
||||
applyBoxI(itRoyalJelly);
|
||||
applyBoxI(itWine);
|
||||
applyBoxI(itSilver);
|
||||
applyBoxI(itEmerald);
|
||||
applyBoxI(itPower);
|
||||
applyBoxI(itOrbFire, true);
|
||||
applyBoxI(itOrbInvis, true);
|
||||
applyBoxI(itOrbAether, true);
|
||||
applyBoxI(itOrbPsi, true);
|
||||
applyBoxOrb(itOrbFire);
|
||||
applyBoxOrb(itOrbInvis);
|
||||
applyBoxOrb(itOrbAether);
|
||||
applyBoxOrb(itOrbPsi);
|
||||
applyBoxM(moBug0);
|
||||
applyBoxM(moBug1);
|
||||
applyBoxM(moBug2);
|
||||
@ -407,12 +442,12 @@ void applyBoxes() {
|
||||
applyBoxM(moCShark);
|
||||
applyBoxM(moParrot);
|
||||
applyBoxI(itPirate);
|
||||
applyBoxI(itOrbTime, true);
|
||||
applyBoxOrb(itOrbTime);
|
||||
|
||||
applyBoxM(moHexSnake);
|
||||
applyBoxM(moRedTroll);
|
||||
applyBoxI(itRedGem);
|
||||
applyBoxI(itOrbSpace, true);
|
||||
applyBoxOrb(itOrbSpace);
|
||||
|
||||
int geo = geometry;
|
||||
applyBoxNum(geo, ""); geometry = eGeometry(geo);
|
||||
@ -429,14 +464,14 @@ void applyBoxes() {
|
||||
applyBoxM(moBomberbird);
|
||||
applyBoxM(moTameBomberbird);
|
||||
applyBoxM(moAlbatross);
|
||||
applyBoxI(itOrbFriend, true);
|
||||
applyBoxI(itOrbAir, true);
|
||||
applyBoxI(itOrbWater, true);
|
||||
applyBoxOrb(itOrbFriend);
|
||||
applyBoxOrb(itOrbAir);
|
||||
applyBoxOrb(itOrbWater);
|
||||
|
||||
applyBoxI(itPalace);
|
||||
applyBoxI(itFjord);
|
||||
applyBoxI(itOrbFrog, true);
|
||||
applyBoxI(itOrbDiscord, true);
|
||||
applyBoxOrb(itOrbFrog);
|
||||
applyBoxOrb(itOrbDiscord);
|
||||
applyBoxM(moPalace);
|
||||
applyBoxM(moFatGuard);
|
||||
applyBoxM(moSkeleton);
|
||||
@ -446,7 +481,7 @@ void applyBoxes() {
|
||||
applyBoxM(moWaterElemental);
|
||||
|
||||
applyBoxI(itSavedPrincess);
|
||||
applyBoxI(itOrbLove, true);
|
||||
applyBoxOrb(itOrbLove);
|
||||
applyBoxM(moPrincess);
|
||||
applyBoxM(moPrincessMoved, false); // live Princess for Safety
|
||||
applyBoxM(moPrincessArmedMoved, false); // live Princess for Safety
|
||||
@ -467,8 +502,8 @@ void applyBoxes() {
|
||||
applyBoxM(moFamiliar);
|
||||
applyBoxM(moGargoyle);
|
||||
applyBoxM(moOrangeDog);
|
||||
applyBoxI(itOrbSummon, true);
|
||||
applyBoxI(itOrbMatter, true);
|
||||
applyBoxOrb(itOrbSummon);
|
||||
applyBoxOrb(itOrbMatter);
|
||||
|
||||
applyBoxM(moForestTroll);
|
||||
applyBoxM(moStormTroll);
|
||||
@ -479,8 +514,8 @@ void applyBoxes() {
|
||||
applyBoxI(itMutant);
|
||||
applyBoxI(itFulgurite);
|
||||
applyBoxI(itBounty);
|
||||
applyBoxI(itOrbLuck, true);
|
||||
applyBoxI(itOrbStunning, true);
|
||||
applyBoxOrb(itOrbLuck);
|
||||
applyBoxOrb(itOrbStunning);
|
||||
|
||||
applyBoxBool(tactic::on, "");
|
||||
applyBoxNum(elec::lightningfast, "");
|
||||
@ -488,22 +523,22 @@ void applyBoxes() {
|
||||
// if(savebox[boxid]) printf("lotus = %d (lost = %d)\n", savebox[boxid], isHaunted(lostin));
|
||||
if(loadingHi && isHaunted(lostin)) boxid++;
|
||||
else applyBoxI(itLotus);
|
||||
applyBoxI(itOrbUndeath, true);
|
||||
applyBoxOrb(itOrbUndeath);
|
||||
applyBoxI(itWindstone);
|
||||
applyBoxI(itOrbEmpathy, true);
|
||||
applyBoxOrb(itOrbEmpathy);
|
||||
applyBoxM(moWindCrow);
|
||||
applyBoxI(itMutant2);
|
||||
applyBoxI(itOrbFreedom, true);
|
||||
applyBoxOrb(itMutant2);
|
||||
applyBoxOrb(itOrbFreedom);
|
||||
applyBoxM(moRedFox);
|
||||
applyBoxBool(survivalist);
|
||||
if(loadingHi) applyBoxI(itLotus);
|
||||
else applyBoxNum(truelotus, "lotus/escape");
|
||||
applyBoxBool(purehepta, "heptagons only");
|
||||
applyBoxI(itRose);
|
||||
applyBoxI(itOrbBeauty, true);
|
||||
applyBoxOrb(itOrbBeauty);
|
||||
applyBoxI(itCoral);
|
||||
applyBoxI(itOrb37, true);
|
||||
applyBoxI(itOrbEnergy, true);
|
||||
applyBoxOrb(itOrb37);
|
||||
applyBoxOrb(itOrbEnergy);
|
||||
applyBoxM(moRatling);
|
||||
applyBoxM(moFalsePrincess);
|
||||
applyBoxM(moRoseLady);
|
||||
@ -520,11 +555,11 @@ void applyBoxes() {
|
||||
applyBoxM(moResearcher);
|
||||
applyBoxI(itDragon);
|
||||
applyBoxM(moDragonHead);
|
||||
applyBoxI(itOrbDomination, true);
|
||||
applyBoxOrb(itOrbDomination);
|
||||
applyBoxI(itBabyTortoise);
|
||||
applyBoxNum(tortoise::seekbits, "");
|
||||
applyBoxM(moTortoise);
|
||||
applyBoxI(itOrbShell, true);
|
||||
applyBoxOrb(itOrbShell);
|
||||
|
||||
applyBoxNum(safetyseed);
|
||||
|
||||
@ -539,12 +574,12 @@ void applyBoxes() {
|
||||
applyBoxI(itKraken);
|
||||
applyBoxM(moKrakenH);
|
||||
applyBoxM(moKrakenT);
|
||||
applyBoxI(itOrbSword, true);
|
||||
applyBoxOrb(itOrbSword);
|
||||
applyBoxI(itBarrow);
|
||||
applyBoxM(moDraugr);
|
||||
applyBoxI(itOrbSword2, true);
|
||||
applyBoxOrb(itOrbSword2);
|
||||
applyBoxI(itTrollEgg);
|
||||
applyBoxI(itOrbStone, true);
|
||||
applyBoxOrb(itOrbStone);
|
||||
|
||||
bool sph;
|
||||
sph = false; applyBoxBool(sph, "sphere"); if(sph) geometry = gSphere;
|
||||
@ -554,22 +589,34 @@ void applyBoxes() {
|
||||
applyBoxI(itDodeca);
|
||||
applyBoxI(itAmethyst);
|
||||
applyBoxI(itSlime);
|
||||
applyBoxI(itOrbNature, true);
|
||||
applyBoxI(itOrbDash, true);
|
||||
// itOrbRecall should not be here
|
||||
applyBoxOrb(itOrbNature);
|
||||
applyBoxOrb(itOrbDash);
|
||||
addinv(itOrbRecall);
|
||||
applyBoxM(moBat);
|
||||
applyBoxM(moReptile);
|
||||
applyBoxM(moFriendlyIvy);
|
||||
|
||||
applyBoxI(itGreenGrass);
|
||||
applyBoxI(itBull);
|
||||
applyBoxI(itOrbHorns, true);
|
||||
applyBoxI(itOrbBull, true);
|
||||
applyBoxOrb(itOrbHorns);
|
||||
applyBoxOrb(itOrbBull);
|
||||
applyBoxM(moSleepBull);
|
||||
applyBoxM(moRagingBull);
|
||||
applyBoxM(moHerdBull);
|
||||
applyBoxM(moButterfly);
|
||||
applyBoxM(moGadfly);
|
||||
|
||||
// 10.0:
|
||||
applyBoxNum(hinttoshow); // 258
|
||||
addinv(itOrbMirror);
|
||||
addinv(itGreenStone);
|
||||
list_invorb();
|
||||
applyBoxBool(inv::on, "inventory"); // 306
|
||||
#ifdef INV
|
||||
applyBoxNum(inv::rseed);
|
||||
#else
|
||||
{ int u; applyBoxNum(u); }
|
||||
#endif
|
||||
|
||||
if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid);
|
||||
}
|
||||
@ -785,6 +832,7 @@ void loadsave() {
|
||||
score sc;
|
||||
bool ok = false;
|
||||
bool tamper = false;
|
||||
int coh = counthints();
|
||||
while(!feof(f)) {
|
||||
char buf[120];
|
||||
if(fgets(buf, 120, f) == NULL) break;
|
||||
@ -792,7 +840,8 @@ void loadsave() {
|
||||
gamecount++;
|
||||
if(fscanf(f, "%s", buf) <= 0) break;
|
||||
sc.ver = buf;
|
||||
if(sc.ver < "4.4" || sc.ver == "CHEATER!") { ok = false; continue; }
|
||||
if(sc.ver[1] != '.') sc.ver = '0' + sc.ver;
|
||||
if(verless(sc.ver, "4.4") || sc.ver == "CHEATER!") { ok = false; continue; }
|
||||
ok = true;
|
||||
for(int i=0; i<MAXBOX; i++) {
|
||||
if(fscanf(f, "%d", &sc.box[i]) <= 0) {
|
||||
@ -803,6 +852,10 @@ void loadsave() {
|
||||
for(int i=0; i<boxid; i++) savebox[i] = sc.box[i];
|
||||
for(int i=boxid; i<MAXBOX; i++) savebox[i] = 0, sc.box[i] = 0;
|
||||
|
||||
if(savebox[258] >= 0 && savebox[258] < coh) {
|
||||
hints[savebox[258]].last = savebox[1];
|
||||
}
|
||||
|
||||
loadBoxHigh();
|
||||
|
||||
break;
|
||||
@ -826,7 +879,10 @@ void loadsave() {
|
||||
|
||||
for(int xc=0; xc<MODECODES; xc++)
|
||||
if(tid == tactic::id && (anticheat::check(cert, ver, dnameof(eLand(land)), tc, t, ts, xc*999+tid + 256 * score))) {
|
||||
if(score != 0 && !(land == laOcean && ver < string("8.0f")))
|
||||
if(score != 0
|
||||
&& !(land == laOcean && verless(ver, "8.0f"))
|
||||
&& !(land == laMirror && verless(ver, "10.0"))
|
||||
)
|
||||
tactic::record(eLand(land), score, xc);
|
||||
anticheat::nextid(tactic::id, ver, cert);
|
||||
break;
|
||||
@ -843,8 +899,8 @@ void loadsave() {
|
||||
if(anticheat::check(cert, ver, won ? "WON" : "LOST", tc, t, ts, xc*999 + cid + 256 * oy)) {
|
||||
if(xc == 19 && cid == 25) xc = 0;
|
||||
if(cid > 0 && cid < YENDORLEVELS)
|
||||
if(!(ver < string("8.0f") && oy > 1 && cid == 15))
|
||||
if(!(ver < string("9.3b") && oy > 1 && (cid == 27 || cid == 28)))
|
||||
if(!(verless(ver, "8.0f") && oy > 1 && cid == 15))
|
||||
if(!(verless(ver, "9.3b") && oy > 1 && (cid == 27 || cid == 28)))
|
||||
{
|
||||
yendor::bestscore[xc][cid] = max(yendor::bestscore[xc][cid], oy);
|
||||
}
|
||||
@ -955,6 +1011,7 @@ void restartGame(char switchWhat, bool push) {
|
||||
#endif
|
||||
achievementsReceived.clear();
|
||||
princess::saved = false;
|
||||
princess::nodungeon = false;
|
||||
princess::reviveAt = 0;
|
||||
princess::forceVizier = false;
|
||||
princess::forceMouse = false;
|
||||
@ -1101,7 +1158,8 @@ eItem randomTreasure2(int cv) {
|
||||
|
||||
bool isTechnicalLand(eLand l) {
|
||||
return l == laNone || l == laOceanWall || l == laBarrier || l == laCanvas ||
|
||||
l == laHauntedWall || l == laHauntedBorder || l == laCA;
|
||||
l == laHauntedWall || l == laHauntedBorder || l == laCA ||
|
||||
l == laMirrorWall || l == laMirrored;
|
||||
}
|
||||
|
||||
eLand cheatdest;
|
||||
|
7
util.cpp
7
util.cpp
@ -29,6 +29,13 @@ string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; }
|
||||
string fts(float x) { char buf[64]; sprintf(buf, "%4.2f", x); return buf; }
|
||||
string fts3(float x) { char buf[64]; sprintf(buf, "%5.3f", x); return buf; }
|
||||
string fts4(float x) { char buf[64]; sprintf(buf, "%6.4f", x); return buf; }
|
||||
|
||||
string ftssmart(ld x) {
|
||||
if(x == int(x)) return its(int(x));
|
||||
if(abs(x) > 1) return fts4(x);
|
||||
char buf[64]; sprintf(buf, "%.10le", (double) x); return buf;
|
||||
}
|
||||
|
||||
string cts(char c) { char buf[8]; buf[0] = c; buf[1] = 0; return buf; }
|
||||
string llts(long long i) {
|
||||
// sprintf does not work on Windows IIRC
|
||||
|
15
yendor.cpp
15
yendor.cpp
@ -7,7 +7,7 @@
|
||||
|
||||
namespace peace { extern bool on; }
|
||||
|
||||
#define MODECODES 254
|
||||
#define MODECODES 255
|
||||
|
||||
int hiitemsMax(eItem it) {
|
||||
int mx = 0;
|
||||
@ -211,6 +211,7 @@ namespace yendor {
|
||||
nyi.path[i] = lig.c;
|
||||
|
||||
cwstep(lig);
|
||||
if(inmirror(lig)) lig = mirror::reflect(lig);
|
||||
cwspin(lig, 3);
|
||||
if(lig.c->type == 7) {
|
||||
if(in_endorian && endorian_change && i >= YDIST - 20) {
|
||||
@ -289,6 +290,8 @@ namespace yendor {
|
||||
c2->wall = waPlatform;
|
||||
if(c2->land == laReptile && i >= 0)
|
||||
c2->wall = waChasm;
|
||||
if(c2->land == laMirrorWall && i == -1)
|
||||
c2->wall = waNone;
|
||||
}
|
||||
key->item = itKey;
|
||||
|
||||
@ -508,14 +511,12 @@ namespace yendor {
|
||||
challenge = uni-'a' + 1;
|
||||
if(levelUnlocked(challenge) || autocheat) {
|
||||
restartGame(yendor::on ? 0 : 'y');
|
||||
popScreen();
|
||||
}
|
||||
else
|
||||
addMessage("Collect 10 treasures in various lands to unlock the challenges there");
|
||||
}
|
||||
else if(uni == '0') {
|
||||
if(yendor::on) restartGame('y');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == '1') easy = !easy;
|
||||
else if(uni == '2' || sym == SDLK_F1) gotoHelp(chelp);
|
||||
@ -744,12 +745,11 @@ namespace tactic {
|
||||
if(uni >= 1000 && uni < 1000 + LAND_TAC) {
|
||||
firstland = euclidland = getLandById(uni - 1000);
|
||||
restartGame(tactic::on ? 0 : 't');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == '0') {
|
||||
popScreen();
|
||||
firstland = laIce;
|
||||
if(tactic::on) restartGame('t');
|
||||
else popScreen();
|
||||
}
|
||||
|
||||
else if(sym == SDLK_F1) gotoHelp(
|
||||
@ -827,7 +827,7 @@ int modecodetable[42][6] = {
|
||||
{248,249,250,251,252,253}, // shmup heptagonal elliptic chaosmode
|
||||
};
|
||||
// unused code: 25
|
||||
int newmodecode = 254;
|
||||
int newmodecode = 255;
|
||||
|
||||
int modecode() {
|
||||
#ifndef NOSAVE
|
||||
@ -838,6 +838,7 @@ int modecode() {
|
||||
if(quotient) return 6;
|
||||
#endif
|
||||
if(peace::on) return 6;
|
||||
if(inv::on) return 254; // no code yet
|
||||
int xcode = 0;
|
||||
|
||||
if(shmup::on) xcode += 2;
|
||||
@ -1049,13 +1050,11 @@ namespace peace {
|
||||
else if(uni >= 'a' && uni < 'a' + qty) {
|
||||
whichland = levellist[uni - 'a'];
|
||||
restartGame(peace::on ? 0 : 'P');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == '2') { hint = !hint; popScreen(); }
|
||||
else if(uni == '0') {
|
||||
firstland = laIce;
|
||||
if(peace::on) restartGame('P');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == 'h' || sym == SDLK_F1) gotoHelp(chelp);
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
|
Loading…
Reference in New Issue
Block a user