Updated the source files to 9.4c
This commit is contained in:
parent
1e3612939c
commit
58e053f183
139
achievement.cpp
139
achievement.cpp
|
@ -1,7 +1,7 @@
|
|||
// Hyperbolic Rogue -- achievements
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#define NUMLEADER 57
|
||||
#define NUMLEADER 69
|
||||
|
||||
#define SCORE_UNKNOWN (-1)
|
||||
#define NO_SCORE_YET (-2)
|
||||
|
@ -16,7 +16,7 @@ const char* leadernames[NUMLEADER] = {
|
|||
"Score", "Diamonds", "Gold", "Spice", "Rubies", "Elixirs",
|
||||
"Shards", "Totems", "Daisies", "Statues", "Feathers", "Sapphires",
|
||||
"Hyperstones", "Time to Win-71", "Turns to Win-71",
|
||||
"Time to 10 Hyperstones-83", "Turns to 10 Hyperstones-83", "Orbs of Yendor",
|
||||
"Time to 10 Hyperstones-94", "Turns to 10 Hyperstones-94", "Orbs of Yendor",
|
||||
"Fern Flowers",
|
||||
"Royal Jellies", "Powerstones", "Silver", "Wine", "Emeralds", "Grimoires",
|
||||
"Holy Grails", "Red Gems", "Pirate Treasures",
|
||||
|
@ -47,8 +47,23 @@ const char* leadernames[NUMLEADER] = {
|
|||
"Tortoise points", // 54
|
||||
"Dragon Scales", // 55
|
||||
"Apples", // 56
|
||||
"Heptagonal Mode", // 57
|
||||
"Sunken Treasures", // 58
|
||||
"Ancient Jewelry", // 59
|
||||
"Golden Eggs", // 60
|
||||
"Multiplayer Score", // 61
|
||||
"Statistics", // 62
|
||||
"Halloween", // 63
|
||||
"Amethysts", // 64
|
||||
"Slime Molds", // 65
|
||||
"Dodecahedra", // 66
|
||||
"Green Grass", // 67
|
||||
"Spinel" // 68
|
||||
};
|
||||
|
||||
#define LB_STATISTICS 62
|
||||
#define LB_HALLOWEEN 63
|
||||
|
||||
bool haveLeaderboard(int id);
|
||||
|
||||
void upload_score(int id, int v);
|
||||
|
@ -59,13 +74,18 @@ int achievementTimer;
|
|||
|
||||
bool wrongMode(char flags) {
|
||||
if(cheater) return true;
|
||||
if(flags == 'x') return false;
|
||||
if(purehepta != (flags == '7')) return true;
|
||||
if(euclid != (flags == 'e')) return true;
|
||||
if(sphere != (flags == 'E')) return true;
|
||||
if((quotient == 1) != (flags == 'q')) return true;
|
||||
if((quotient == 2) != (flags == 'Q')) return true;
|
||||
if(shmup::on != (flags == 's')) return true;
|
||||
if(randomPatternsMode) return true;
|
||||
if(yendor::on) return true;
|
||||
if(tactic::on) return true;
|
||||
if(chaosmode != (flags == 'C')) return true;
|
||||
if((numplayers() > 1) != (flags == 'm')) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -80,10 +100,13 @@ void achievement_log(const char* s, char flags) {
|
|||
for(int i=0; i<size(achievementsReceived); i++)
|
||||
if(achievementsReceived[i] == s) return;
|
||||
achievementsReceived.push_back(s);
|
||||
|
||||
#ifndef NOSAVE
|
||||
remove_emergency_save();
|
||||
|
||||
#ifndef ANDROID
|
||||
FILE *f = fopen(scorefile, "at");
|
||||
if(!f) return;
|
||||
|
||||
int t = (int) (time(NULL) - timerstart);
|
||||
|
||||
time_t timer = time(NULL);
|
||||
|
@ -101,6 +124,7 @@ void improveItemScores();
|
|||
#include "hypersteam.cpp"
|
||||
#else
|
||||
#ifndef ANDROID
|
||||
#ifndef IOS
|
||||
void achievement_init() {}
|
||||
void achievement_close() {}
|
||||
void achievement_gain(const char* s, char flags) {
|
||||
|
@ -108,11 +132,18 @@ void achievement_gain(const char* s, char flags) {
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void achievement_collection(eItem it, int prevgold, int newgold) {
|
||||
if(cheater) return;
|
||||
if(randomPatternsMode) return;
|
||||
int q = items[it];
|
||||
|
||||
if(it == itTreat && q == 50)
|
||||
achievement_gain("HALLOWEEN1", 'E');
|
||||
|
||||
if(it == itTreat && q == 100)
|
||||
achievement_gain("HALLOWEEN2", 'E');
|
||||
|
||||
if(q == 1) {
|
||||
if(it == itDiamond) achievement_gain("DIAMOND1");
|
||||
|
@ -142,7 +173,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itPalace) achievement_gain("RUG1");
|
||||
if(it == itFjord) achievement_gain("GARNET1");
|
||||
|
||||
if(it == itEdge) achievement_gain("TOWER1");
|
||||
if(it == itIvory) achievement_gain("TOWER1");
|
||||
if(it == itElemental) achievement_gain("ELEMENT1");
|
||||
if(it == itZebra) achievement_gain("ZEBRA1");
|
||||
|
||||
|
@ -157,6 +188,17 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itBabyTortoise) achievement_gain("TORTOISE1");
|
||||
if(it == itDragon) achievement_gain("DRAGON1");
|
||||
if(it == itApple) achievement_gain("APPLE1");
|
||||
|
||||
if(it == itKraken) achievement_gain("KRAKEN1");
|
||||
if(it == itBarrow) achievement_gain("BARROW1");
|
||||
if(it == itTrollEgg) achievement_gain("TROLL1");
|
||||
|
||||
if(it == itAmethyst) achievement_gain("MOUNT1");
|
||||
if(it == itSlime) achievement_gain("DUNG1");
|
||||
if(it == itDodeca) achievement_gain("DOD1");
|
||||
|
||||
if(it == itGreenGrass) achievement_gain("PRAIR1");
|
||||
if(it == itBull) achievement_gain("BULL1");
|
||||
}
|
||||
|
||||
// 32
|
||||
|
@ -194,7 +236,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itPalace) achievement_gain("RUG2");
|
||||
if(it == itFjord) achievement_gain("GARNET2");
|
||||
|
||||
if(it == itEdge) achievement_gain("TOWER2");
|
||||
if(it == itIvory) achievement_gain("TOWER2");
|
||||
if(it == itElemental) achievement_gain("ELEMENT2");
|
||||
if(it == itZebra) achievement_gain("ZEBRA2");
|
||||
|
||||
|
@ -209,6 +251,17 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itBabyTortoise) achievement_gain("TORTOISE2");
|
||||
if(it == itDragon) achievement_gain("DRAGON2");
|
||||
if(it == itApple) achievement_gain("APPLE2");
|
||||
|
||||
if(it == itKraken) achievement_gain("KRAKEN2");
|
||||
if(it == itBarrow) achievement_gain("BARROW2");
|
||||
if(it == itTrollEgg) achievement_gain("TROLL2");
|
||||
|
||||
if(it == itAmethyst) achievement_gain("MOUNT2");
|
||||
if(it == itSlime) achievement_gain("DUNG2");
|
||||
if(it == itDodeca) achievement_gain("DOD2");
|
||||
|
||||
if(it == itGreenGrass) achievement_gain("PRAIR2");
|
||||
if(it == itBull) achievement_gain("BULL2");
|
||||
}
|
||||
|
||||
if(q == 25) {
|
||||
|
@ -239,7 +292,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itPalace) achievement_gain("RUG3");
|
||||
if(it == itFjord) achievement_gain("GARNET3");
|
||||
|
||||
if(it == itEdge) achievement_gain("TOWER3");
|
||||
if(it == itIvory) achievement_gain("TOWER3");
|
||||
if(it == itElemental) achievement_gain("ELEMENT3");
|
||||
if(it == itZebra) achievement_gain("ZEBRA3");
|
||||
|
||||
|
@ -257,6 +310,17 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itBabyTortoise) achievement_gain("TORTOISE3");
|
||||
if(it == itDragon) achievement_gain("DRAGON3");
|
||||
if(it == itApple) achievement_gain("APPLE3");
|
||||
|
||||
if(it == itKraken) achievement_gain("KRAKEN3");
|
||||
if(it == itBarrow) achievement_gain("BARROW3");
|
||||
if(it == itTrollEgg) achievement_gain("TROLL3");
|
||||
|
||||
if(it == itAmethyst) achievement_gain("MOUNT3");
|
||||
if(it == itSlime) achievement_gain("DUNG3");
|
||||
if(it == itDodeca) achievement_gain("DOD3");
|
||||
|
||||
if(it == itGreenGrass) achievement_gain("PRAIR3");
|
||||
if(it == itBull) achievement_gain("BULL3");
|
||||
}
|
||||
|
||||
if(q == 50) {
|
||||
|
@ -287,7 +351,7 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itPalace) achievement_gain("RUG4");
|
||||
if(it == itFjord) achievement_gain("GARNET4");
|
||||
|
||||
if(it == itEdge) achievement_gain("TOWER4");
|
||||
if(it == itIvory) achievement_gain("TOWER4");
|
||||
if(it == itElemental) achievement_gain("ELEMENT4");
|
||||
if(it == itZebra) achievement_gain("ZEBRA4");
|
||||
|
||||
|
@ -302,6 +366,17 @@ void achievement_collection(eItem it, int prevgold, int newgold) {
|
|||
if(it == itBabyTortoise) achievement_gain("TORTOISE4");
|
||||
if(it == itDragon) achievement_gain("DRAGON4");
|
||||
if(it == itApple) achievement_gain("APPLE4");
|
||||
|
||||
if(it == itKraken) achievement_gain("KRAKEN4");
|
||||
if(it == itBarrow) achievement_gain("BARROW4");
|
||||
if(it == itTrollEgg) achievement_gain("TROLL4");
|
||||
|
||||
if(it == itAmethyst) achievement_gain("MOUNT4");
|
||||
if(it == itSlime) achievement_gain("DUNG4");
|
||||
if(it == itDodeca) achievement_gain("DOD4");
|
||||
|
||||
if(it == itGreenGrass) achievement_gain("PRAIR4");
|
||||
if(it == itBull) achievement_gain("BULL4");
|
||||
}
|
||||
|
||||
if(it == itOrbYendor) {
|
||||
|
@ -323,6 +398,8 @@ void achievement_count(const string& s, int current, int prev) {
|
|||
achievement_gain("STABBER1");
|
||||
if(s == "STAB" && current >= 2)
|
||||
achievement_gain("STABBER2");
|
||||
if(s == "SLASH" && current >= 2)
|
||||
achievement_gain("SLASH2");
|
||||
if(s == "STAB" && current >= 4)
|
||||
achievement_gain("STABBER3");
|
||||
if(s == "MIRRORKILL" && current-prev >= 1)
|
||||
|
@ -374,6 +451,9 @@ void achievement_score(int cat, int number) {
|
|||
#ifdef HAVE_ACHIEVEMENTS
|
||||
if(cheater) return;
|
||||
if(euclid) return;
|
||||
if(sphere && cat != LB_HALLOWEEN) return;
|
||||
if(quotient) return;
|
||||
if(elliptic && cat != LB_HALLOWEEN) return;
|
||||
if(purehepta) return;
|
||||
if(randomPatternsMode) return;
|
||||
if(shmup::on && cat != LB_PURE_TACTICS_SHMUP && cat != LB_PURE_TACTICS_COOP) return;
|
||||
|
@ -403,7 +483,7 @@ void improveItemScores() {
|
|||
improve_score(34, itPalace);
|
||||
improve_score(35, itFjord);
|
||||
|
||||
improve_score(37, itEdge);
|
||||
improve_score(37, itIvory);
|
||||
improve_score(38, itElemental);
|
||||
improve_score(39, itZebra);
|
||||
|
||||
|
@ -420,14 +500,34 @@ void improveItemScores() {
|
|||
improve_score(54, itBabyTortoise);
|
||||
improve_score(55, itDragon);
|
||||
improve_score(56, itApple);
|
||||
|
||||
improve_score(58, itKraken);
|
||||
improve_score(59, itBarrow);
|
||||
improve_score(60, itTrollEgg);
|
||||
|
||||
improve_score(64, itAmethyst);
|
||||
improve_score(65, itSlime);
|
||||
improve_score(66, itDodeca);
|
||||
|
||||
improve_score(67, itGreenGrass);
|
||||
improve_score(68, itBull);
|
||||
}
|
||||
|
||||
void achievement_final(bool really_final) {
|
||||
if(offlineMode) return;
|
||||
#ifdef HAVE_ACHIEVEMENTS
|
||||
upload_score(LB_STATISTICS, time(NULL));
|
||||
if(cheater) return;
|
||||
|
||||
if(sphere && euclidland == laHalloween) {
|
||||
if(shmup::on || chaosmode || purehepta || numplayers() > 1 || tactic::on || randomPatternsMode)
|
||||
return;
|
||||
achievement_score(LB_HALLOWEEN, items[itTreat]);
|
||||
}
|
||||
|
||||
if(euclid) return;
|
||||
if(purehepta) return;
|
||||
if(sphere) return;
|
||||
if(elliptic) return;
|
||||
if(randomPatternsMode) return;
|
||||
|
||||
if(tactic::on) {
|
||||
|
@ -439,15 +539,24 @@ void achievement_final(bool really_final) {
|
|||
|
||||
if(yendor::on) return;
|
||||
|
||||
if(shmup::on && chaosmode) return;
|
||||
// no leaderboards for two special modes at once
|
||||
int specials = 0;
|
||||
if(shmup::on) specials++;
|
||||
if(chaosmode) specials++;
|
||||
if(purehepta) specials++;
|
||||
if(specials > 1) return;
|
||||
|
||||
if(numplayers() > 1 && chaosmode) return;
|
||||
if(numplayers() > 1 && purehepta) return;
|
||||
|
||||
int total_improved = 0;
|
||||
specific_improved = 0;
|
||||
specific_what = 0;
|
||||
|
||||
if(!shmup::on && !chaosmode) improveItemScores();
|
||||
if(!shmup::on && !chaosmode && !purehepta && numplayers() == 1) improveItemScores();
|
||||
|
||||
int sid = chaosmode ? 53 : shmup::on ? (numplayers() > 1 ? 44 : 28) : 0;
|
||||
int sid = purehepta ? 57 : chaosmode ? 53 : shmup::on ? (numplayers() > 1 ? 44 : 28) :
|
||||
(numplayers() > 1 ? 61 : 0);
|
||||
|
||||
int tg = gold();
|
||||
if(tg && haveLeaderboard(sid)) {
|
||||
|
@ -488,6 +597,8 @@ void achievement_victory(bool hyper) {
|
|||
#ifdef HAVE_ACHIEVEMENTS
|
||||
if(cheater) return;
|
||||
if(euclid) return;
|
||||
if(sphere) return;
|
||||
if(quotient) return;
|
||||
if(purehepta) return;
|
||||
if(randomPatternsMode) return;
|
||||
if(hyper && shmup::on) return;
|
||||
|
@ -572,3 +683,7 @@ void achievement_display() {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool isAscending(int i) {
|
||||
return i == 13 || i == 14 || i == 15 || i == 16 || i == 29 || i == 30 || i == 45;
|
||||
};
|
||||
|
||||
|
|
650
cell.cpp
650
cell.cpp
|
@ -1,10 +1,11 @@
|
|||
|
||||
// Hyperbolic Rogue -- cells
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
// cells the game is played on
|
||||
|
||||
int fix6(int a) { return (a+96)% 6; }
|
||||
int fix7(int a) { return (a+84)% 7; }
|
||||
int fix7(int a) { return (a+420)%S7; }
|
||||
|
||||
int dirdiff(int dd, int t) {
|
||||
dd %= t;
|
||||
|
@ -15,7 +16,20 @@ int dirdiff(int dd, int t) {
|
|||
|
||||
struct cell : gcell {
|
||||
char type; // 6 for hexagons, 7 for heptagons
|
||||
unsigned char spn[7];
|
||||
|
||||
// wall parameter, used for remaining power of Bonfires and Thumpers
|
||||
char wparam;
|
||||
|
||||
// 'tmp' is used for:
|
||||
// pathfinding algorithm used by monsters with atypical movement (which do not use pathdist)
|
||||
// bugs' pathfinding algorithm
|
||||
short aitmp;
|
||||
|
||||
uint32_t spintable;
|
||||
int spin(int d) { return tspin(spintable, d); }
|
||||
int spn(int d) { return tspin(spintable, d); }
|
||||
int mirror(int d) { return tmirror(spintable, d); }
|
||||
|
||||
heptagon *master;
|
||||
cell *mov[7]; // meaning very similar to heptagon::move
|
||||
};
|
||||
|
@ -36,11 +50,11 @@ cell *newCell(int type, heptagon *master) {
|
|||
return c;
|
||||
}
|
||||
|
||||
void merge(cell *c, int d, cell *c2, int d2) {
|
||||
void merge(cell *c, int d, cell *c2, int d2, bool mirrored = false) {
|
||||
c->mov[d] = c2;
|
||||
c->spn[d] = d2;
|
||||
tsetspin(c->spintable, d, d2 + (mirrored?8:0));
|
||||
c2->mov[d2] = c;
|
||||
c2->spn[d2] = d;
|
||||
tsetspin(c2->spintable, d2, d + (mirrored?8:0));
|
||||
}
|
||||
|
||||
typedef unsigned short eucoord;
|
||||
|
@ -80,55 +94,54 @@ cell *createMov(cell *c, int d) {
|
|||
if(c->mov[d]) return c->mov[d];
|
||||
else if(purehepta) {
|
||||
heptagon *h2 = createStep(c->master, d);
|
||||
c->mov[d] = h2->c7;
|
||||
c->spn[d] = c->master->spin[d];
|
||||
h2->c7->mov[c->spn[d]] = c;
|
||||
h2->c7->spn[c->spn[d]] = d;
|
||||
merge(c,d,h2->c7,c->master->spin(d),false);
|
||||
}
|
||||
else if(c->type == 7) {
|
||||
else if(c->type != 6) {
|
||||
cell *n = newCell(6, c->master);
|
||||
|
||||
c->mov[d] = n; n->mov[0] = c;
|
||||
c->spn[d] = 0; n->spn[0] = d;
|
||||
merge(c,d,n,0,false);
|
||||
|
||||
heptspin hs; hs.h = c->master; hs.spin = d;
|
||||
heptspin hs; hs.h = c->master; hs.spin = d; hs.mirrored = false;
|
||||
|
||||
heptspin hs2 = hsstep(hsspin(hs, 3), 3);
|
||||
int a3 = c->type/2;
|
||||
int a4 = a3+1;
|
||||
|
||||
// merge(hs2.h->c7, hs2.spin, n, 2);
|
||||
heptspin hs2 = hsstep(hsspin(hs, a3), a3);
|
||||
merge(hs2.h->c7, hs2.spin, n, 2, hs2.mirrored);
|
||||
|
||||
hs2.h->c7->mov[hs2.spin] = n; n->mov[2] = hs2.h->c7;
|
||||
hs2.h->c7->spn[hs2.spin] = 2; n->spn[2] = hs2.spin;
|
||||
|
||||
hs2 = hsstep(hsspin(hs, 4), 4);
|
||||
// merge(hs2.h->c7, hs2.spin, n, 4);
|
||||
hs2.h->c7->mov[hs2.spin] = n; n->mov[4] = hs2.h->c7;
|
||||
hs2.h->c7->spn[hs2.spin] = 4; n->spn[4] = hs2.spin;
|
||||
heptspin hs3 = hsstep(hsspin(hs, a4), a4);
|
||||
merge(hs3.h->c7, hs3.spin, n, 4, hs3.mirrored);
|
||||
|
||||
extern void verifycell(cell *c);
|
||||
verifycell(n);
|
||||
}
|
||||
|
||||
else if(d == 5) {
|
||||
int di = fixrot(c->spn[0]+1);
|
||||
int di = fixrot(c->spin(0)+1);
|
||||
cell *c2 = createMov(c->mov[0], di);
|
||||
merge(c, 5, c2, fix6(c->mov[0]->spn[di] + 1));
|
||||
bool mirr = c->mov[0]->mirror(di);
|
||||
merge(c, 5, c2, fix6(c->mov[0]->spn(di) + (mirr?-1:1)), mirr);
|
||||
|
||||
// c->mov[5] = c->mov[0]->mov[fixrot(c->spn[0]+1)];
|
||||
// c->spn[5] = fix6(c->mov[0]->spn[fixrot(c->spn[0]+1)] + 1);
|
||||
}
|
||||
|
||||
else if(d == 1) {
|
||||
int di = fixrot(c->spn[0]-1);
|
||||
int di = fixrot(c->spn(0)-1);
|
||||
cell *c2 = createMov(c->mov[0], di);
|
||||
merge(c, 1, c2, fix6(c->mov[0]->spn[di] - 1));
|
||||
bool mirr = c->mov[0]->mirror(di);
|
||||
merge(c, 1, c2, fix6(c->mov[0]->spn(di) - (mirr?-1:1)), mirr);
|
||||
|
||||
// c->mov[1] = c->mov[0]->mov[fixrot(c->spn[0]-1)];
|
||||
// c->spn[1] = fix6(c->mov[0]->spn[fixrot(c->spn[0]-1)] - 1);
|
||||
}
|
||||
|
||||
else if(d == 3) {
|
||||
int di = fixrot(c->spn[2]-1);
|
||||
bool mirr = c->mirror(2);
|
||||
int di = fixrot(c->spn(2)-(mirr?-1:1));
|
||||
cell *c2 = createMov(c->mov[2], di);
|
||||
merge(c, 3, c2, fix6(c->mov[2]->spn[di] - 1));
|
||||
bool nmirr = mirr ^ c->mov[2]->mirror(di);
|
||||
merge(c, 3, c2, fix6(c->mov[2]->spn(di) - (nmirr?-1:1)), nmirr);
|
||||
// c->mov[3] = c->mov[2]->mov[fixrot(c->spn[2]-1)];
|
||||
// c->spn[3] = fix6(c->mov[2]->spn[fixrot(c->spn[2]-1)] - 1);
|
||||
}
|
||||
|
@ -136,12 +149,12 @@ cell *createMov(cell *c, int d) {
|
|||
}
|
||||
|
||||
cell *createMovR(cell *c, int d) {
|
||||
d %= 42; d += 42; d %= c->type;
|
||||
d %= 420; d += 420; d %= c->type;
|
||||
return createMov(c, d);
|
||||
}
|
||||
|
||||
cell *getMovR(cell *c, int d) {
|
||||
d %= 42; d += 42; d %= c->type;
|
||||
d %= 420; d += 420; d %= c->type;
|
||||
return c->mov[d];
|
||||
}
|
||||
|
||||
|
@ -149,12 +162,13 @@ cell *getMovR(cell *c, int d) {
|
|||
struct cellwalker {
|
||||
cell *c;
|
||||
int spin;
|
||||
cellwalker(cell *c, int spin) : c(c), spin(spin) {}
|
||||
cellwalker() {}
|
||||
bool mirrored;
|
||||
cellwalker(cell *c, int spin) : c(c), spin(spin) { mirrored = false; }
|
||||
cellwalker() { mirrored = false; }
|
||||
};
|
||||
|
||||
void cwspin(cellwalker& cw, int d) {
|
||||
cw.spin = (cw.spin+d + 42) % cw.c->type;
|
||||
cw.spin = (cw.spin+(MIRR(cw)?-d:d) + 420) % cw.c->type;
|
||||
}
|
||||
|
||||
bool cwstepcreates(cellwalker& cw) {
|
||||
|
@ -162,20 +176,21 @@ bool cwstepcreates(cellwalker& cw) {
|
|||
}
|
||||
|
||||
cell *cwpeek(cellwalker cw, int dir) {
|
||||
return createMov(cw.c, (cw.spin+42+dir) % cw.c->type);
|
||||
return createMov(cw.c, (cw.spin+420+dir) % cw.c->type);
|
||||
}
|
||||
|
||||
void cwstep(cellwalker& cw) {
|
||||
createMov(cw.c, cw.spin);
|
||||
int nspin = cw.c->spn[cw.spin];
|
||||
int nspin = cw.c->spn(cw.spin);
|
||||
if(cw.c->mirror(cw.spin)) cw.mirrored = !cw.mirrored;
|
||||
cw.c = cw.c->mov[cw.spin];
|
||||
cw.spin = nspin;
|
||||
}
|
||||
|
||||
void eumerge(cell* c1, cell *c2, int s1, int s2) {
|
||||
if(!c2) return;
|
||||
c1->mov[s1] = c2; c1->spn[s1] = s2;
|
||||
c2->mov[s2] = c1; c2->spn[s2] = s1;
|
||||
c1->mov[s1] = c2; tsetspin(c1->spintable, s1, s2);
|
||||
c2->mov[s2] = c1; tsetspin(c2->spintable, s2, s1);
|
||||
}
|
||||
|
||||
struct euclideanSlab {
|
||||
|
@ -216,28 +231,99 @@ cell*& euclideanAtCreate(eucoord x, eucoord y) {
|
|||
return c;
|
||||
}
|
||||
|
||||
int spherecells() {
|
||||
if(S7 == 5) return (elliptic?6:12);
|
||||
if(S7 == 4) return (elliptic?3:6);
|
||||
if(S7 == 3) return 4;
|
||||
if(S7 == 2) return (elliptic?1:2);
|
||||
if(S7 == 1) return 1;
|
||||
return 12;
|
||||
}
|
||||
|
||||
// initializer (also inits origin from heptagon.cpp)
|
||||
void initcells() {
|
||||
DEBB(DF_INIT, (debugfile,"initcells\n"));
|
||||
|
||||
origin.s = hsOrigin;
|
||||
origin.emeraldval = 98;
|
||||
origin.zebraval = 40;
|
||||
origin.fiftyval = 0;
|
||||
#ifdef CDATA
|
||||
origin.rval0 = origin.rval1 = 0;
|
||||
origin.cdata = NULL;
|
||||
#endif
|
||||
|
||||
for(int i=0; i<7; i++) origin.move[i] = NULL;
|
||||
origin.alt = NULL;
|
||||
origin.distance = 0;
|
||||
if(euclid)
|
||||
origin.c7 = euclideanAtCreate(0,0);
|
||||
else
|
||||
origin.c7 = newCell(7, &origin);
|
||||
|
||||
if(sphere) {
|
||||
for(int i=0; i<spherecells(); i++) {
|
||||
heptagon& h = dodecahedron[i];
|
||||
h.s = hsOrigin;
|
||||
h.emeraldval = i;
|
||||
h.zebraval = i;
|
||||
h.fiftyval = i;
|
||||
h.rval0 = h.rval1 = 0;
|
||||
h.alt = NULL;
|
||||
h.cdata = NULL;
|
||||
h.spintable = 0;
|
||||
for(int i=0; i<S7; i++) h.move[i] = NULL;
|
||||
h.c7 = newCell(S7, &h);
|
||||
}
|
||||
for(int i=0; i<S7; i++) {
|
||||
dodecahedron[0].move[i] = &dodecahedron[i+1];
|
||||
dodecahedron[0].setspin(i, 0);
|
||||
dodecahedron[i+1].move[0] = &dodecahedron[0];
|
||||
dodecahedron[i+1].setspin(0, i);
|
||||
|
||||
dodecahedron[i+1].move[1] = &dodecahedron[(i+S7-1)%S7+1];
|
||||
dodecahedron[i+1].setspin(1, S7-1);
|
||||
dodecahedron[i+1].move[S7-1] = &dodecahedron[(i+1)%S7+1];
|
||||
dodecahedron[i+1].setspin(S7-1, 1);
|
||||
|
||||
if(S7 == 5 && elliptic) {
|
||||
dodecahedron[i+1].move[2] = &dodecahedron[(i+2)%S7+1];
|
||||
dodecahedron[i+1].setspin(2, 3 + 8);
|
||||
dodecahedron[i+1].move[3] = &dodecahedron[(i+3)%S7+1];
|
||||
dodecahedron[i+1].setspin(3, 2 + 8);
|
||||
}
|
||||
|
||||
else if(S7 == 5) {
|
||||
dodecahedron[6].move[i] = &dodecahedron[7+i];
|
||||
dodecahedron[6].setspin(i, 0);
|
||||
dodecahedron[7+i].move[0] = &dodecahedron[6];
|
||||
dodecahedron[7+i].setspin(0, i);
|
||||
|
||||
dodecahedron[i+7].move[1] = &dodecahedron[(i+4)%5+7];
|
||||
dodecahedron[i+7].setspin(1, 4);
|
||||
dodecahedron[i+7].move[4] = &dodecahedron[(i+1)%5+7];
|
||||
dodecahedron[i+7].setspin(4, 1);
|
||||
|
||||
dodecahedron[i+1].move[2] = &dodecahedron[7+(10-i)%5];
|
||||
dodecahedron[i+1].setspin(2, 2);
|
||||
dodecahedron[7+(10-i)%5].move[2] = &dodecahedron[1+i];
|
||||
dodecahedron[7+(10-i)%5].setspin(2, 2);
|
||||
|
||||
dodecahedron[i+1].move[3] = &dodecahedron[7+(9-i)%5];
|
||||
dodecahedron[i+1].setspin(3, 3);
|
||||
dodecahedron[7+(9-i)%5].move[3] = &dodecahedron[i+1];
|
||||
dodecahedron[7+(9-i)%5].setspin(3, 3);
|
||||
}
|
||||
if(S7 == 4) {
|
||||
dodecahedron[5].move[3-i] = &dodecahedron[i+1];
|
||||
dodecahedron[5].setspin(3-i, 2);
|
||||
dodecahedron[i+1].move[2] = &dodecahedron[5];
|
||||
dodecahedron[i+1].setspin(2, 3-i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
origin.s = hsOrigin;
|
||||
origin.emeraldval = 98;
|
||||
origin.zebraval = 40;
|
||||
origin.fiftyval = 0;
|
||||
origin.fieldval = 0;
|
||||
origin.rval0 = origin.rval1 = 0;
|
||||
origin.cdata = NULL;
|
||||
for(int i=0; i<7; i++) origin.move[i] = NULL;
|
||||
origin.spintable = 0;
|
||||
origin.alt = NULL;
|
||||
origin.distance = 0;
|
||||
if(euclid)
|
||||
origin.c7 = euclideanAtCreate(0,0);
|
||||
else
|
||||
origin.c7 = newCell(7, &origin);
|
||||
}
|
||||
|
||||
if(quotient) quotientspace::build();
|
||||
// origin.emeraldval =
|
||||
}
|
||||
|
||||
|
@ -247,13 +333,13 @@ void clearcell(cell *c) {
|
|||
if(!c) return;
|
||||
DEBMEM ( printf("c%d %p\n", c->type, c); )
|
||||
for(int t=0; t<c->type; t++) if(c->mov[t]) {
|
||||
DEBMEM ( printf("mov %p [%p] S%d\n", c->mov[t], c->mov[t]->mov[c->spn[t]], c->spn[t]); )
|
||||
if(c->mov[t]->mov[c->spn[t]] != NULL &&
|
||||
c->mov[t]->mov[c->spn[t]] != c) {
|
||||
DEBMEM ( printf("mov %p [%p] S%d\n", c->mov[t], c->mov[t]->mov[c->spn(t)], c->spn(t)); )
|
||||
if(c->mov[t]->mov[c->spn(t)] != NULL &&
|
||||
c->mov[t]->mov[c->spn(t)] != c) {
|
||||
printf("cell error\n");
|
||||
exit(1);
|
||||
}
|
||||
c->mov[t]->mov[c->spn[t]] = NULL;
|
||||
c->mov[t]->mov[c->spn(t)] = NULL;
|
||||
}
|
||||
DEBMEM ( printf("DEL %p\n", c); )
|
||||
delete c;
|
||||
|
@ -261,6 +347,14 @@ void clearcell(cell *c) {
|
|||
|
||||
heptagon deletion_marker;
|
||||
|
||||
void clearHexes(heptagon *at) {
|
||||
if(at->c7) {
|
||||
if(!purehepta) for(int i=0; i<7; i++)
|
||||
clearcell(at->c7->mov[i]);
|
||||
clearcell(at->c7);
|
||||
}
|
||||
}
|
||||
|
||||
#include <queue>
|
||||
void clearfrom(heptagon *at) {
|
||||
queue<heptagon*> q;
|
||||
|
@ -276,22 +370,16 @@ void clearfrom(heptagon *at) {
|
|||
if(at->move[i]->alt != &deletion_marker)
|
||||
q.push(at->move[i]);
|
||||
at->move[i]->alt = &deletion_marker;
|
||||
DEBMEM ( printf("!mov %p [%p]\n", at->move[i], at->move[i]->move[at->spin[i]]); )
|
||||
if(at->move[i]->move[at->spin[i]] != NULL &&
|
||||
at->move[i]->move[at->spin[i]] != at) {
|
||||
DEBMEM ( printf("!mov %p [%p]\n", at->move[i], at->move[i]->move[at->spin(i)]); )
|
||||
if(at->move[i]->move[at->spin(i)] != NULL &&
|
||||
at->move[i]->move[at->spin(i)] != at) {
|
||||
printf("hept error\n");
|
||||
exit(1);
|
||||
}
|
||||
at->move[i]->move[at->spin[i]] = NULL;
|
||||
at->move[i]->move[at->spin(i)] = NULL;
|
||||
at->move[i] = NULL;
|
||||
}
|
||||
DEBMEM ( printf("at %p\n", at); )
|
||||
if(at->c7) {
|
||||
if(!purehepta) for(int i=0; i<7; i++)
|
||||
clearcell(at->c7->mov[i]);
|
||||
clearcell(at->c7);
|
||||
}
|
||||
DEBMEM ( printf("!DEL %p\n", at); )
|
||||
clearHexes(at);
|
||||
if(at != &origin) delete at;
|
||||
}
|
||||
//printf("maxq = %d\n", maxq);
|
||||
|
@ -302,46 +390,49 @@ void verifycell(cell *c) {
|
|||
for(int i=0; i<t; i++) {
|
||||
cell *c2 = c->mov[i];
|
||||
if(c2) {
|
||||
if(t == 7 && !purehepta) verifycell(c2);
|
||||
if(c2->mov[c->spn[i]] && c2->mov[c->spn[i]] != c)
|
||||
printf("cell error %p %p\n", c, c2);
|
||||
if(t != 6 && !purehepta) verifycell(c2);
|
||||
if(c2->mov[c->spn(i)] && c2->mov[c->spn(i)] != c) {
|
||||
printf("cell error %p:%d [%d] %p:%d [%d]\n", c, i, c->type, c2, c->spn(i), c2->type);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void verifycells(heptagon *at) {
|
||||
for(int i=0; i<7; i++) if(at->move[i] && at->spin[i] == 0 && at->move[i] != &origin)
|
||||
verifycells(at->move[i]);
|
||||
for(int i=0; i<7; i++) if(at->move[i] && at->move[i]->move[at->spin[i]] && at->move[i]->move[at->spin[i]] != at) {
|
||||
printf("hexmix error %p %p %p\n", at, at->move[i], at->move[i]->move[at->spin[i]]);
|
||||
for(int i=0; i<7; i++) if(at->move[i] && at->move[i]->move[at->spin(i)] && at->move[i]->move[at->spin(i)] != at) {
|
||||
printf("hexmix error %p [%d s=%d] %p %p\n", at, i, at->spin(i), at->move[i], at->move[i]->move[at->spin(i)]);
|
||||
}
|
||||
if(!sphere && !quotient) for(int i=0; i<7; i++) if(at->move[i] && at->spin(i) == 0 && at->move[i] != &origin)
|
||||
verifycells(at->move[i]);
|
||||
verifycell(at->c7);
|
||||
}
|
||||
|
||||
int eupattern(cell *c) {
|
||||
eucoord x, y;
|
||||
decodeMaster(c->master, x, y);
|
||||
short z = (short(y+2*x))%3;
|
||||
z %= 3;
|
||||
if(z<0) z += 3;
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
bool ishept(cell *c) {
|
||||
// EUCLIDEAN
|
||||
if(euclid) {
|
||||
eucoord x, y;
|
||||
decodeMaster(c->master, x, y);
|
||||
return (short(y+2*x))%3 == 0;
|
||||
}
|
||||
else return c->type == 7;
|
||||
if(euclid) return eupattern(c) == 0;
|
||||
else return c->type != 6;
|
||||
}
|
||||
|
||||
bool ishex1(cell *c) {
|
||||
// EUCLIDEAN
|
||||
if(euclid) {
|
||||
eucoord x, y;
|
||||
decodeMaster(c->master, x, y);
|
||||
short z = (short(y+2*x))%3;
|
||||
if(z<0) z += 3;
|
||||
return z == 1;
|
||||
}
|
||||
if(euclid) return eupattern(c) == 1;
|
||||
else return c->type == 7;
|
||||
}
|
||||
|
||||
int emeraldval(cell *c) {
|
||||
if(euclid) return 0;
|
||||
if(euclid) return eupattern(c);
|
||||
if(sphere) return 0;
|
||||
if(c->type == 7)
|
||||
return c->master->emeraldval >> 3;
|
||||
else {
|
||||
|
@ -360,6 +451,17 @@ int eudist(short sx, short sy) {
|
|||
return max(max(z0,z1), z2);
|
||||
}
|
||||
|
||||
int compdist(int dx[3]) {
|
||||
int mi = min(min(dx[0], dx[1]), dx[2]);
|
||||
if(dx[0] > mi+2 || dx[1] > mi+2 || dx[2] > mi+2)
|
||||
return -1; // { printf("cycle error!\n"); exit(1); }
|
||||
if(dx[0] == mi+2 || dx[1] == mi+2 || dx[2] == mi+2)
|
||||
return mi+1;
|
||||
if((dx[0] == mi+1) + (dx[1] == mi+1) + (dx[2] == mi+1) >= 2)
|
||||
return mi+1;
|
||||
return mi;
|
||||
}
|
||||
|
||||
int celldist(cell *c) {
|
||||
if(euclid) {
|
||||
eucoord x, y;
|
||||
|
@ -370,12 +472,7 @@ int celldist(cell *c) {
|
|||
int dx[3];
|
||||
for(int u=0; u<3; u++)
|
||||
dx[u] = createMov(c, u+u)->master->distance;
|
||||
int mi = min(min(dx[0], dx[1]), dx[2]);
|
||||
if(dx[0] > mi+2 || dx[1] > mi+2 || dx[2] > mi+2)
|
||||
return -1; // { printf("cycle error!\n"); exit(1); }
|
||||
if(dx[0] == mi+2 || dx[1] == mi+2 || dx[2] == mi+2)
|
||||
return mi+1;
|
||||
return mi;
|
||||
return compdist(dx);
|
||||
}
|
||||
|
||||
#define ALTDIST_BOUNDARY 99999
|
||||
|
@ -392,6 +489,7 @@ int celldistAlt(cell *c) {
|
|||
decodeMaster(c->master, x, y);
|
||||
return euclidAlt(x, y);
|
||||
}
|
||||
if(!c->master->alt) return 0;
|
||||
if(c->type == 7) return c->master->alt->distance;
|
||||
int dx[3];
|
||||
for(int u=0; u<3; u++) if(createMov(c, u+u)->master->alt == NULL)
|
||||
|
@ -420,8 +518,23 @@ unsigned bitmajority(unsigned a, unsigned b, unsigned c) {
|
|||
return (a&b) | ((a^b)&c);
|
||||
}
|
||||
|
||||
int eufifty(cell *c) {
|
||||
eucoord x, y;
|
||||
decodeMaster(c->master, x, y);
|
||||
int ix = short(x) + 99999 + short(y);
|
||||
int iy = short(y) + 99999;
|
||||
if(c->land == laWildWest)
|
||||
return (ix + iy * 26 + 28) % 37;
|
||||
else {
|
||||
ix += (iy/3) * 3;
|
||||
iy %= 3; ix %= 9;
|
||||
return iy * 9 + ix;
|
||||
}
|
||||
}
|
||||
|
||||
int fiftyval(cell *c) {
|
||||
if(euclid) return 0;
|
||||
if(euclid) return eufifty(c) * 32;
|
||||
if(sphere) return 0;
|
||||
if(c->type == 7)
|
||||
return c->master->fiftyval;
|
||||
else {
|
||||
|
@ -433,26 +546,11 @@ int fiftyval(cell *c) {
|
|||
}
|
||||
|
||||
int cdist50(cell *c) {
|
||||
if(sphere) return 0;
|
||||
if(euclid) {
|
||||
eucoord x, y;
|
||||
decodeMaster(c->master, x, y);
|
||||
int ix = short(x) + 99999 + short(y);
|
||||
int iy = short(y) + 99999;
|
||||
if(c->land == laPalace) {
|
||||
char palacemap[3][10] = {
|
||||
"012333321",
|
||||
"112322232",
|
||||
"222321123"
|
||||
};
|
||||
ix += (iy/3) * 3;
|
||||
iy %= 3; ix %= 9;
|
||||
return palacemap[iy][ix] - '0';
|
||||
}
|
||||
else {
|
||||
const char *westmap = "0123333332112332223322233211233333322";
|
||||
int id = ix + iy * 26 + 28;
|
||||
return westmap[id % 37] - '0';
|
||||
}
|
||||
if(c->land == laWildWest)
|
||||
return "0123333332112332223322233211233333322"[eufifty(c)] - '0';
|
||||
else return "012333321112322232222321123"[eufifty(c)] - '0';
|
||||
}
|
||||
if(c->type == 7) return cdist50(fiftyval(c));
|
||||
int a0 = cdist50(createMov(c,0));
|
||||
|
@ -464,6 +562,7 @@ int cdist50(cell *c) {
|
|||
|
||||
int land50(cell *c) {
|
||||
if(c->type == 7) return land50(fiftyval(c));
|
||||
else if(sphere || euclid) return 0;
|
||||
else {
|
||||
if(cdist50(createMov(c,0)) < 3) return land50(createMov(c,0));
|
||||
if(cdist50(createMov(c,2)) < 3) return land50(createMov(c,2));
|
||||
|
@ -474,6 +573,7 @@ int land50(cell *c) {
|
|||
|
||||
int polara50(cell *c) {
|
||||
if(c->type == 7) return polara50(fiftyval(c));
|
||||
else if(sphere || euclid) return 0;
|
||||
else {
|
||||
if(cdist50(createMov(c,0)) < 3) return polara50(createMov(c,0));
|
||||
if(cdist50(createMov(c,2)) < 3) return polara50(createMov(c,2));
|
||||
|
@ -485,6 +585,7 @@ int polara50(cell *c) {
|
|||
int polarb50(cell *c) {
|
||||
if(euclid) return true;
|
||||
if(c->type == 7) return polarb50(fiftyval(c));
|
||||
else if(sphere || euclid) return true;
|
||||
else {
|
||||
if(cdist50(createMov(c,0)) < 3) return polarb50(createMov(c,0));
|
||||
if(cdist50(createMov(c,2)) < 3) return polarb50(createMov(c,2));
|
||||
|
@ -498,7 +599,8 @@ int elhextable[28][3] = {
|
|||
};
|
||||
|
||||
int fiftyval049(cell *c) {
|
||||
if(c->type == 7) return fiftyval(c) / 32;
|
||||
if(c->type == 7 || euclid) return fiftyval(c) / 32;
|
||||
else if(sphere) return 0;
|
||||
else {
|
||||
int a[3], qa=0;
|
||||
int pa = polara50(c), pb = polarb50(c);
|
||||
|
@ -536,7 +638,9 @@ int fiftyval049(cell *c) {
|
|||
|
||||
int zebra40(cell *c) {
|
||||
if(c->type == 7) return (c->master->zebraval/10);
|
||||
else {
|
||||
else if(sphere) return 0;
|
||||
else if(euclid) return eupattern(c);
|
||||
else {
|
||||
int ii[3], z;
|
||||
ii[0] = (c->mov[0]->master->zebraval/10);
|
||||
ii[1] = (c->mov[2]->master->zebraval/10);
|
||||
|
@ -558,6 +662,7 @@ int zebra40(cell *c) {
|
|||
|
||||
int zebra3(cell *c) {
|
||||
if(c->type == 7) return (c->master->zebraval/10)/4;
|
||||
else if(sphere) return 0;
|
||||
else {
|
||||
int ii[3];
|
||||
ii[0] = (c->mov[0]->master->zebraval/10)/4;
|
||||
|
@ -696,8 +801,6 @@ bool randpatternMajority(cell *c, int ival, int iterations) {
|
|||
return memo;
|
||||
}
|
||||
|
||||
#ifdef CDATA
|
||||
|
||||
#include <map>
|
||||
map<heptagon*, int> spins;
|
||||
|
||||
|
@ -732,6 +835,8 @@ void setHeptagonRval(heptagon *h) {
|
|||
cdata *getHeptagonCdata(heptagon *h) {
|
||||
if(h->cdata) return h->cdata;
|
||||
|
||||
if(sphere || quotient) h = &origin;
|
||||
|
||||
if(h == &origin) {
|
||||
return h->cdata = new cdata(orig_cdata);
|
||||
}
|
||||
|
@ -876,8 +981,108 @@ eLand getCLand(cell *c) {
|
|||
return land_scape[b & 31];
|
||||
}
|
||||
|
||||
// list all cells in distance at most maxdist, or until when maxcount cells are reached
|
||||
|
||||
struct celllister {
|
||||
vector<cell*> lst;
|
||||
vector<int> tmps;
|
||||
vector<int> dists;
|
||||
|
||||
bool listed(cell *c) {
|
||||
return c->aitmp >= 0 && c->aitmp < size(lst) && lst[c->aitmp] == c;
|
||||
}
|
||||
|
||||
void add(cell *c, int d) {
|
||||
if(listed(c)) return;
|
||||
c->aitmp = size(lst);
|
||||
tmps.push_back(c->aitmp);
|
||||
lst.push_back(c);
|
||||
dists.push_back(d);
|
||||
}
|
||||
|
||||
int getdist(cell *c) { return dists[c->aitmp]; }
|
||||
|
||||
~celllister() {
|
||||
for(int i=0; i<size(lst); i++) lst[i]->aitmp = tmps[i];
|
||||
}
|
||||
|
||||
celllister(cell *orig, int maxdist, int maxcount, cell *breakon) {
|
||||
lst.clear();
|
||||
tmps.clear();
|
||||
dists.clear();
|
||||
add(orig, 0);
|
||||
cell *last = orig;
|
||||
for(int i=0; i<size(lst); i++) {
|
||||
cell *c = lst[i];
|
||||
if(maxdist) forCellCM(c2, c) {
|
||||
add(c2, dists[i]+1);
|
||||
if(c2 == breakon) return;
|
||||
}
|
||||
if(c == last) {
|
||||
if(size(lst) >= maxcount || dists[i]+1 == maxdist) break;
|
||||
last = lst[size(lst)-1];
|
||||
maxdist--;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cell *heptatdir(cell *c, int d) {
|
||||
if(d&1) {
|
||||
cell *c2 = createMov(c, d);
|
||||
int s = c->spin(d);
|
||||
s += 3; s %= 6;
|
||||
return createMov(c2, s);
|
||||
}
|
||||
else return createMov(c, d);
|
||||
}
|
||||
|
||||
namespace fieldpattern {
|
||||
|
||||
pair<int, bool> fieldval(cell *c) {
|
||||
if(c->type == 7) return make_pair(c->master->fieldval, false);
|
||||
else return make_pair(btspin(c->master->fieldval, c->spin(0)), true);
|
||||
}
|
||||
|
||||
int subpathid = fp43.matcode[fp43.strtomatrix("RRRPRRRRRPRRRP")];
|
||||
int subpathorder = fp43.order(fp43.matrices[subpathid]);
|
||||
|
||||
pair<int, int> subval(cell *c, int _subpathid = subpathid, int _subpathorder = subpathorder) {
|
||||
if(c->type == 6)
|
||||
return min(min(subval(createMov(c, 0)),subval(createMov(c, 2))), subval(createMov(c, 4)));
|
||||
else {
|
||||
pair<int, int> pbest, pcur;
|
||||
pcur.first = c->master->fieldval;
|
||||
pcur.second = 0;
|
||||
pbest = pcur;
|
||||
for(int i=0; i<_subpathorder; i++) {
|
||||
pcur.first = fp43.gmul(pcur.first, _subpathid);
|
||||
pcur.second++;
|
||||
if(pcur < pbest) pbest = pcur;
|
||||
}
|
||||
return pbest;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
int celldistance(cell *c1, cell *c2) {
|
||||
int d = 0;
|
||||
|
||||
if(euclid) {
|
||||
eucoord x1, y1, x2, y2;
|
||||
decodeMaster(c1->master, x1, y1);
|
||||
decodeMaster(c2->master, x2, y2);
|
||||
return eudist(x1-x2, y1-y2);
|
||||
}
|
||||
|
||||
if(sphere || quotient == 1) {
|
||||
celllister cl(c1, 64, 1000, c2);
|
||||
return cl.getdist(c2);
|
||||
}
|
||||
|
||||
if(quotient == 2)
|
||||
return fp43.getdist(fieldpattern::fieldval(c1), fieldpattern::fieldval(c2));
|
||||
|
||||
cell *cl1=c1, *cr1=c1, *cl2=c2, *cr2=c2;
|
||||
while(true) {
|
||||
if(cl1 == cl2) return d;
|
||||
|
@ -912,16 +1117,20 @@ int celldistance(cell *c1, cell *c2) {
|
|||
}
|
||||
}
|
||||
|
||||
void clearMemory() {
|
||||
extern void clearGameMemory();
|
||||
clearGameMemory();
|
||||
if(shmup::on) shmup::clearMemory();
|
||||
cleargraphmemory();
|
||||
#ifndef MOBILE
|
||||
mapeditor::clearModelCells();
|
||||
#endif
|
||||
void clearHyperbolicMemory() {
|
||||
DEBMEM ( verifycells(&origin); )
|
||||
clearfrom(&origin);
|
||||
for(int i=0; i<size(allAlts); i++) clearfrom(allAlts[i]);
|
||||
allAlts.clear();
|
||||
}
|
||||
|
||||
void clearCellMemory() {
|
||||
// EUCLIDEAN
|
||||
if(euclid) {
|
||||
if(sphere) {
|
||||
for(int i=0; i<spherecells(); i++) clearHexes(&dodecahedron[i]);
|
||||
}
|
||||
else if(quotient) quotientspace::clear();
|
||||
else if(euclid) {
|
||||
for(int y=0; y<256; y++) for(int x=0; x<256; x++)
|
||||
if(euclidean[y][x]) {
|
||||
delete euclidean[y][x];
|
||||
|
@ -929,13 +1138,182 @@ void clearMemory() {
|
|||
}
|
||||
eucdata.clear();
|
||||
}
|
||||
else {
|
||||
DEBMEM ( verifycells(&origin); )
|
||||
clearfrom(&origin);
|
||||
for(int i=0; i<size(allAlts); i++) clearfrom(allAlts[i]);
|
||||
allAlts.clear();
|
||||
}
|
||||
else clearHyperbolicMemory();
|
||||
}
|
||||
|
||||
void clearMemory() {
|
||||
extern void clearGameMemory();
|
||||
clearGameMemory();
|
||||
shmup::clearMemory();
|
||||
cleargraphmemory();
|
||||
#ifndef NOEDIT
|
||||
mapeditor::clearModelCells();
|
||||
#endif
|
||||
clearCellMemory();
|
||||
DEBMEM ( printf("ok\n"); )
|
||||
}
|
||||
|
||||
#endif
|
||||
void verifyDodecahedron() {
|
||||
for(int i=0; i<spherecells(); i++) for(int k=0; k<S7; k++) {
|
||||
heptspin hs;
|
||||
hs.h = &dodecahedron[i];
|
||||
hs.spin = k;
|
||||
hs = hsstep(hs, 0);
|
||||
hs = hsspin(hs, S7-1);
|
||||
hs = hsstep(hs, 0);
|
||||
hs = hsspin(hs, S7-1);
|
||||
hs = hsstep(hs, 0);
|
||||
hs = hsspin(hs, S7-1);
|
||||
if(hs.h != &dodecahedron[i]) printf("error %d,%d\n", i, k);
|
||||
}
|
||||
for(int i=0; i<spherecells(); i++) verifycells(&dodecahedron[i]);
|
||||
}
|
||||
|
||||
int getHemisphere(cell *c, int which) {
|
||||
if(c->type != 6) {
|
||||
int id = c->master->fiftyval;
|
||||
int hemitable[3][12] = {
|
||||
{ 6, 3, 3, 3, 3, 3,-6,-3,-3,-3,-3,-3},
|
||||
{ 6, 3, 6, 3, 0, 0,-6,-3,-6,-3, 0, 0},
|
||||
{-3, 0, 3, 0,-6,-6, 3, 0,-3, 0, 6, 6}
|
||||
};
|
||||
return hemitable[which][id];
|
||||
}
|
||||
else {
|
||||
int score = 0;
|
||||
for(int i=0; i<6; i+=2)
|
||||
score += getHemisphere(c->mov[i], which);
|
||||
return score/3;
|
||||
}
|
||||
}
|
||||
|
||||
namespace quotientspace {
|
||||
|
||||
vector<cell*> allcells;
|
||||
|
||||
struct code {
|
||||
int c[8];
|
||||
};
|
||||
|
||||
bool operator == (const code& c1, const code &c2) {
|
||||
for(int i=0; i<8; i++) if(c1.c[i] != c2.c[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator < (const code& c1, const code &c2) {
|
||||
for(int i=0; i<8; i++) if(c1.c[i] != c2.c[i]) return c1.c[i] < c2.c[i];
|
||||
return false;
|
||||
}
|
||||
|
||||
map<code, int> reachable;
|
||||
vector<heptspin> bfsq;
|
||||
|
||||
int cod(heptagon *h) {
|
||||
return zebra40(h->c7);
|
||||
}
|
||||
|
||||
code get(heptspin hs) {
|
||||
code res;
|
||||
res.c[0] = cod(hs.h);
|
||||
for(int i=1; i<8; i++) {
|
||||
res.c[i] = cod(hsstep(hs, 0).h);
|
||||
hs = hsspin(hs, 1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<int> connections;
|
||||
|
||||
int rvadd = 0, rvdir = 1;
|
||||
|
||||
int rv(int x) { return (rvadd+x*rvdir) % 7; } // if(x) return 7-x; else return x; }
|
||||
|
||||
void add(const heptspin& hs) {
|
||||
code g = get(hs);
|
||||
if(!reachable.count(g)) {
|
||||
reachable[g] = bfsq.size();
|
||||
bfsq.push_back(hs);
|
||||
add(hsspin(hs, 1));
|
||||
}
|
||||
}
|
||||
|
||||
vector<heptagon*> allh;
|
||||
|
||||
void clear() {
|
||||
clearfrom(origin.alt);
|
||||
for(int i=0; i<size(allh); i++) {
|
||||
clearHexes(allh[i]);
|
||||
if(i) delete allh[i];
|
||||
}
|
||||
allh.clear();
|
||||
allcells.clear();
|
||||
}
|
||||
|
||||
void build() {
|
||||
|
||||
if(quotient == 2) {
|
||||
connections = fp43.connections;
|
||||
}
|
||||
else {
|
||||
heptspin hs; hs.h = &origin; hs.spin = 0;
|
||||
reachable.clear();
|
||||
bfsq.clear();
|
||||
connections.clear();
|
||||
add(hs);
|
||||
|
||||
for(int i=0; i<(int)bfsq.size(); i++) {
|
||||
hs = hsstep(bfsq[i], 0);
|
||||
add(hs);
|
||||
connections.push_back(reachable[get(hs)]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clearHyperbolicMemory();
|
||||
origin.c7 = newCell(7, &origin);
|
||||
|
||||
int TOT = connections.size() / 7;
|
||||
printf("heptagons = %d\n", TOT);
|
||||
printf("all cells = %d\n", TOT*10/3);
|
||||
if(!TOT) exit(1);
|
||||
allh.resize(TOT);
|
||||
for(int i=0; i<TOT; i++) allh[i] = i==0 ? &origin : new heptagon;
|
||||
origin.alt = new heptagon;
|
||||
*origin.alt = origin;
|
||||
for(int i=0; i<7; i++) origin.alt->move[i] = NULL;
|
||||
origin.alt->c7 = newCell(7, origin.alt);
|
||||
|
||||
for(int i=0; i<TOT; i++) {
|
||||
heptagon *h = allh[i];
|
||||
if(i) {
|
||||
h->alt = NULL;
|
||||
h->s = hsOrigin;
|
||||
h->emeraldval = 0;
|
||||
h->zebraval = 0;
|
||||
h->fiftyval = 0;
|
||||
h->fieldval = 7*i;
|
||||
h->rval0 = h->rval1 = 0; h->cdata = NULL;
|
||||
h->distance = 0;
|
||||
h->c7 = newCell(7, h);
|
||||
}
|
||||
for(int j=0; j<7; j++) {
|
||||
h->move[rv(j)] = allh[connections[i*7+j]/7];
|
||||
h->setspin(rv(j), rv(connections[i*7+j]%7));
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<TOT; i++) {
|
||||
generateAlts(allh[i]);
|
||||
allh[i]->emeraldval = allh[i]->alt->emeraldval;
|
||||
allh[i]->zebraval = allh[i]->alt->zebraval;
|
||||
allh[i]->fiftyval = allh[i]->alt->fiftyval;
|
||||
allh[i]->distance = allh[i]->alt->distance;
|
||||
/* for(int j=0; j<7; j++)
|
||||
allh[i]->move[j]->alt = createStep(allh[i]->alt, j); */
|
||||
}
|
||||
|
||||
celllister cl(origin.c7, 100, 100000000, NULL);
|
||||
allcells = cl.lst;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
411
classes.cpp
411
classes.cpp
|
@ -1,11 +1,6 @@
|
|||
// Hyperbolic Rogue -- items, monsters, walls, lands, descriptions, etc.
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#define GEN_M 0
|
||||
#define GEN_F 1
|
||||
#define GEN_N 2
|
||||
#define GEN_O 3
|
||||
|
||||
// --- help ---
|
||||
|
||||
const char *wormdes =
|
||||
|
@ -110,7 +105,7 @@ const char *foresthelp =
|
|||
"Trees catch fire on the next turn. The temperature of the grass cells "
|
||||
"rises once per turn for each fire nearby, and becomes fire itself "
|
||||
"when its temperature has risen 10 times.\n"
|
||||
"You can also cut down the trees. Big trees take two turns to cut down.";
|
||||
"You can also chop down the trees. Big trees take two turns to chop down.";
|
||||
|
||||
const char *hivehelp =
|
||||
"The Hive is filled with Hyperbugs. They are huge insects which look a bit like "
|
||||
|
@ -216,13 +211,36 @@ const char *winddesc =
|
|||
"outcoming wind. However, you can move two cells with the wind in a single turn, "
|
||||
"and so can the birds.";
|
||||
|
||||
const char *warningdesc =
|
||||
"Warnings are issued when you try to do something that appears dangerous, "
|
||||
"like stepping on a known mine, or getting your boat destroyed by "
|
||||
"a Kraken without having Orb of the Fish. In some cases the action "
|
||||
"might actually be safe -- so you can ignore the warning and do it anyway, "
|
||||
"simply by repeating the action.";
|
||||
|
||||
const char *hauntdesc =
|
||||
"A dark forest filled with ghosts and graves. But there is also treasure hidden "
|
||||
"deep within... But don't let greed make you stray from your path, as "
|
||||
"you can get lost!\n\n"
|
||||
"The Haunted Woods are bounded by a single equidistant curve. It is not a circle or horocycle.\n\n";
|
||||
|
||||
const char *bulldashdesc =
|
||||
"Butterflies don't pursue you -- unless you get next to them, they just spin around the obstacles. "
|
||||
"They cannot be killed conventionally, but you get treasure when a Raging Bull crashes into a Butterfly. ";
|
||||
|
||||
const char *prairiedesc =
|
||||
"You can find safety in some places in the Prairie, but if you want treasures, "
|
||||
"they can be found only on the other side of a giant herd of bulls.";
|
||||
|
||||
const char *cadesc =
|
||||
"A land for people wanting to experiment with cellular automata in the HyperRogue grid. "
|
||||
"Rules can be given on the command line; the default rules are:\n"
|
||||
"-c07 00100000 -c06 0010000 -c17 00011000 -c16 0001100 -caprob 0.3\n"
|
||||
"(-c0 or -c1 can be given if the same rule is to be used for hexagonal "
|
||||
"and heptagonal cells).";
|
||||
|
||||
const char *NODESC = "No description yet.";
|
||||
const char *NODESCYET = "No description yet.";
|
||||
const char *GENDERSWITCH = NODESC;
|
||||
|
||||
// --- monsters ---
|
||||
|
@ -259,8 +277,8 @@ const char *dragondesc =
|
|||
"The head will regenerate on the "
|
||||
"turns the Dragon is not moving, so you will usually have to hit it with "
|
||||
"your last attack; otherwise, if the head is healthy, it may breathe "
|
||||
"fire (at range 3), losing the hitpoint. Killing the Dragon gives you "
|
||||
"treasure.";
|
||||
"fire (at range 3), losing the hitpoint. Killing the Dragon "
|
||||
"while still in the Dragon Chasms gives you treasure.";
|
||||
|
||||
const char *tortoisedesc =
|
||||
"Galápagos is the land of Tortoises. "
|
||||
|
@ -275,8 +293,49 @@ const char *tortoisedesc =
|
|||
"Bringing back a Baby Tortoise counts as 5 $$$. The more factors agree in "
|
||||
"the given location of Galápagos, the brighter it is shown on your screen.";
|
||||
|
||||
const char *krakendesc =
|
||||
"There are Krakens in your homeland too... huge sea monsters which "
|
||||
"could easily destroy ships. The geometry of this strange world "
|
||||
"prevents quick movement of huge objects, "
|
||||
"so there are no large ships, only small boats, and "
|
||||
"hyperbolic Krakens are relatively small too. Still, you suppose they might be "
|
||||
"the widest creatures which could still move at considerable speed...\n\n"
|
||||
|
||||
"Kraken heads can move only on hexagons. You need to attack all the tentacles to "
|
||||
"kill the Kraken. A tentacle cannot attack if it has been attacked on the "
|
||||
"same turn. When a Kraken attacks you while you are in a boat, it "
|
||||
"destroys the boat, but does not kill you.";
|
||||
|
||||
const int motypes = 125;
|
||||
const char *halloweendesc =
|
||||
"Halloween is a special land, that is available only in the spherical "
|
||||
"or elliptic geometry (press 'o' to switch). You play on the surface of "
|
||||
"a jack-o'-lantern, "
|
||||
"and have to collect as many Treats as possible. Each Treat you collect "
|
||||
"brings new monsters to fight, and new magical powers for you. You "
|
||||
"have to fight the monsters while effectively managing your limited "
|
||||
"resources.";
|
||||
|
||||
const char *reptiledesc =
|
||||
"These reptiles are quite strange creatures. They "
|
||||
"spend most of their lives sleeping as floors "
|
||||
"that other creatures can walk on. "
|
||||
"Sometimes they wake up to hunt their prey, "
|
||||
"but they will happily go back to sleep if they "
|
||||
"happen to move into a hole on their way. "
|
||||
"Your attacks do not kill the Reptiles, but "
|
||||
"you can push and stun them.";
|
||||
|
||||
const char *naturedesc =
|
||||
"This Orb allows you to grow like an Ivy. "
|
||||
"The Ivy is always rooted in your current location; "
|
||||
"moving among the Ivy cells will move the root. "
|
||||
"Moving to a new location will cause the Ivy to grow "
|
||||
", if an Ivy could make that movement "
|
||||
"(otherwise it breaks). "
|
||||
"You can also target one of the cells adjacent to your ivy "
|
||||
"(not to you) to grow or attack there.";
|
||||
|
||||
const int motypes = 139;
|
||||
|
||||
struct monstertype {
|
||||
char glyph;
|
||||
|
@ -474,7 +533,7 @@ monstertype minf[motypes] = {
|
|||
{ 'B', 0x909000, "Slime Beast", slimehelp},
|
||||
{ '@', 0x8080FF, "Knight", camelothelp }, // knight moved
|
||||
{ '@', 0x8B4513, "Illusion",
|
||||
"Illusions are targetted "
|
||||
"Illusions are targeted "
|
||||
"by most monsters, just like yourself, Thumpers, and your friends."
|
||||
},
|
||||
{ 'P', 0xD00000, "Pirate",
|
||||
|
@ -526,7 +585,7 @@ monstertype minf[motypes] = {
|
|||
{ 'P', 0xFF80FF, "Princess", princessdesc},
|
||||
{ 'P', 0xFF80FF, "Prince", princessdesc},
|
||||
{ 'P', 0xFF80FF, "Princess", princessdesc},
|
||||
{ 'S', 0xC0C0C0, "Servant", "A simple servant of the master of the Ivory Tower."},
|
||||
{ 'F', 0xD03000, "Familiar", "A simple servant of the master of the Ivory Tower."},
|
||||
{ 'B', 0x707070, "Gargoyle", gargdesc},
|
||||
{ 'E', 0xFF0000, "Fire Elemental",
|
||||
"This monster leaves a trail of fire behind."},
|
||||
|
@ -573,7 +632,7 @@ monstertype minf[motypes] = {
|
|||
{ 'T', 0x487830, "Tortoise", tortoisedesc},
|
||||
{ 'D', 0xC03000, "Dragon", dragondesc},
|
||||
{ 'd', 0xC03000, "Dragon", dragondesc},
|
||||
{ 'N', 0x303030, "Nighthawk", NODESC},
|
||||
{ 'F', 0x909090, "Gadfly", "Annoying insects. They can awaken Sleeping Bulls."},
|
||||
{ 'Y', 0xFF8000, "Yendorian Researcher",
|
||||
"These people study gravity and infinite trees. "
|
||||
"They have no special features, other than wearing a strange hat."
|
||||
|
@ -581,6 +640,39 @@ monstertype minf[motypes] = {
|
|||
{ 'K', 0xA8A8A8, "Sparrowhawk",
|
||||
"A bird who hunts in the treetops of Yendorian Forest."
|
||||
},
|
||||
{ 'K', 0xD0A0A0, "Kraken", krakendesc},
|
||||
{ 'K', 0xC07070, "Kraken Tentacle", krakendesc},
|
||||
{ 'D', 0xF09090, "Draugr",
|
||||
"Animated corpses of ancient Viking warriors. They are immune to mundane weapons, "
|
||||
"but they can be destroyed by your Orb of the Sword."
|
||||
},
|
||||
{ 'C', 0xC08000, "Friendly Ivy", naturedesc },
|
||||
{ 'V', 0xC000C0, "Vampire Bat",
|
||||
"Vampire Bats don't attack normally, but they drain your magical powers if "
|
||||
"they are at distance at most 2 from you."
|
||||
},
|
||||
{ 'B', 0x404040, "Bat",
|
||||
"Someone has told you that one can get battle experience safely by "
|
||||
"killing tons of essentially harmless creatures, such as Bats. But "
|
||||
"does this make any sense?...\n\n"
|
||||
"It does not. Bats cannot hurt you, but may block your movement, or "
|
||||
"toggle switches if they fall on them." },
|
||||
{ 'R', 0x8080C0, "Reptile", reptiledesc },
|
||||
{ 'B', 0x606020, "Herd Bull",
|
||||
"Herds of these Bulls are running long distances for some reason. They become Raging Bulls if something stops them." },
|
||||
{ 'B', 0xA03000, "Raging Bull",
|
||||
"Raging Bulls charge in a straight line: on heptagons, when they can choose one of two possible directions, "
|
||||
"they choose one closer to your current location. In the case of a tie, the cell where more neighbors is "
|
||||
"closer to your current location is chosen; if still a tie, past locations are considered. "
|
||||
"They can attack you in any direction, and monsters on their way are attacked even if friendly. "
|
||||
"When they crash into something, the obstacle is usually destroyed, and they are stunned for three turns, after "
|
||||
"which they charge at you again (in any direction). "
|
||||
"Raging Bulls cannot be killed or stunned conventionally."
|
||||
},
|
||||
{ 'B', 0xB07000, "Sleeping Bull",
|
||||
"Sleeping bulls wake up when you get into distance of two cells from them."
|
||||
},
|
||||
{ 'S', 0xFFD500, "Butterfly", bulldashdesc},
|
||||
|
||||
// shmup specials
|
||||
{ '@', 0xC0C0C0, "Rogue", "In the Shoot'em Up mode, you are armed with thrown Knives."},
|
||||
|
@ -593,6 +685,9 @@ monstertype minf[motypes] = {
|
|||
{ '?', 0x00C000, "dead bug", NODESC},
|
||||
{ '?', 0xFFFF00, "electric discharge", NODESC}, // appears as 'killed by electrocution'
|
||||
{ '?', 0xE06000, "dead bird", NODESC},
|
||||
{ '?', 0xE06000, "Energy Sword", NODESC},
|
||||
{ '!', 0xFF0000, "Warning", warningdesc},
|
||||
{ '*', 0, "vertex", "A vertex from rogueviz."}
|
||||
};
|
||||
|
||||
enum eMonster {
|
||||
|
@ -626,18 +721,23 @@ enum eMonster {
|
|||
moMouse, moMouseMoved,
|
||||
moPrincess, moPrincessMoved,
|
||||
moPrincessArmed, moPrincessArmedMoved,
|
||||
moEdgeMonkey, moGargoyle, moFireElemental, moAirElemental,
|
||||
moFamiliar, moGargoyle, moFireElemental, moAirElemental,
|
||||
moOrangeDog, moTentacleGhost,
|
||||
moMetalBeast, moMetalBeast2, moOutlaw, moMutant,
|
||||
moStormTroll, moForestTroll,
|
||||
moRedFox, moWindCrow, moFriendlyGhost, moRatling, moFalsePrincess, moRoseLady,
|
||||
moRoseBeauty, moRatlingAvenger,
|
||||
moTortoise, moDragonHead, moDragonTail,
|
||||
moNighthawk, moLemur, moKestrel,
|
||||
moGadfly, moResearcher, moSparrowhawk,
|
||||
moKrakenH, moKrakenT, moDraugr, moFriendlyIvy,
|
||||
moVampire, moBat, moReptile,
|
||||
moHerdBull, moRagingBull, moSleepBull,
|
||||
moButterfly,
|
||||
// shmup specials
|
||||
moPlayer, moBullet, moFlailBullet, moFireball, moTongue, moAirball,
|
||||
// temporary
|
||||
moDeadBug, moLightningBolt, moDeadBird
|
||||
moDeadBug, moLightningBolt, moDeadBird, moEnergySword, moWarning,
|
||||
moRogueviz
|
||||
};
|
||||
|
||||
struct genderswitch_t {
|
||||
|
@ -667,7 +767,7 @@ genderswitch_t genderswitch[NUM_GS] = {
|
|||
|
||||
// --- items ---
|
||||
|
||||
const int ittypes = 92;
|
||||
const int ittypes = 110;
|
||||
|
||||
struct itemtype {
|
||||
char glyph;
|
||||
|
@ -694,7 +794,7 @@ itemtype iinf[ittypes] = {
|
|||
},
|
||||
{ '!', 0xFFFF00, "Elixir of Life",
|
||||
"A wonderful beverage, apparently obtained by mixing red and blue slime. You definitely feel more "
|
||||
"healthy after drinking it, but you still fell that one hit of a monster is enough to kill you."},
|
||||
"healthy after drinking it, but you still feel that one hit of a monster is enough to kill you."},
|
||||
{ '%', 0xFF00FF, "Shard",
|
||||
"A piece of a magic mirror, or a mirage cloud, that can be used for magical purposes. Only mirrors and clouds "
|
||||
"in the Land of Mirrors leave these."},
|
||||
|
@ -798,7 +898,7 @@ itemtype iinf[ittypes] = {
|
|||
"Each fire drains 5 charges. You are not allowed to throw fire into adjacent cells."
|
||||
},
|
||||
{ 'o', 0x8B4513, "Orb of Trickery",
|
||||
"This Orb allows you to create illusions of yourself. Illusions are targetted "
|
||||
"This Orb allows you to create illusions of yourself. Illusions are targeted "
|
||||
"by most monsters, just like yourself, Thumpers, and your friends.\n\n"
|
||||
"Each illusion takes 5 charges to create, and one extra charge "
|
||||
"per turn. You can also click your illusion to take it away, restoring 4 charges.\n\n"
|
||||
|
@ -991,7 +1091,67 @@ itemtype iinf[ittypes] = {
|
|||
"you have to dismount this turn -- be very careful to make this possible, "
|
||||
"as your mount could attack you immediately!\n\n" "While riding, "
|
||||
"click on a location to order your mount to move or attack there.",
|
||||
}
|
||||
},
|
||||
{ 'o', 0xFFFF80, "Orb of the Sword",
|
||||
"This Orb gives you a weapon made of pure magical energy. You do not hold "
|
||||
"it, it simply floats in the air next to you. When you go, the energy sword moves "
|
||||
"with you, pointing at the same relative angle it pointed before -- you cannot "
|
||||
"move or rotate it otherwise. Most monsters can be killed by moving the sword into them, "
|
||||
"and won't move into the spot with the sword."
|
||||
},
|
||||
{ 'x', 0x4040FF, "Sunken Treasure",
|
||||
"Cargo of a ship which was once destroyed by a Kraken." },
|
||||
{ 'o', 0xFF8040, "Orb of the Sword II",
|
||||
"An alternative version of Orb of the Sword. If you have both of them, "
|
||||
"you have two energy swords, facing in opposite directions."
|
||||
},
|
||||
{ '*', 0xFFFF80, "Ancient Jewelry",
|
||||
"Precious belongings of ancient Viking heroes. Your Orb of the Sword can be "
|
||||
"used to dig these treasures out of the barrows."
|
||||
},
|
||||
{ '!', 0xFFD700, "Golden Egg",
|
||||
"Trolls of Trollheim are descendants of a bridge Troll, who collected "
|
||||
"payments from people crossing the bridge. One of them paid with "
|
||||
"golden eggs. The bridge Troll found the eggs beautiful, but he quickly lost them. "
|
||||
"Golden eggs are still revered by Trolls, and you can find them in their "
|
||||
"caves."
|
||||
},
|
||||
{ '!', 0xFF0000, "Warning", warningdesc
|
||||
},
|
||||
{ 'o', 0x808080, "Orb of the Stone",
|
||||
"Trolls turn into stone walls when they die. When you have this Orb, "
|
||||
"this happens to every monster you defeat. Statues created from this Orb "
|
||||
"have slightly different properties than Trolls who petrify naturally."
|
||||
},
|
||||
{ 'o', 0xC08000, "Orb of Nature", naturedesc },
|
||||
{ '%', 0x800080, "Treat", halloweendesc },
|
||||
{ '%', 0x30A030, "Slime Mold",
|
||||
"A very interesting species of slime mold."
|
||||
},
|
||||
{ '*', 0xFF00FF, "Amethyst", "A beatiful purple gem from the Lost Mountain." },
|
||||
{ 'o', 0xC00040, "Orb of Recall",
|
||||
"When the charges on this Orb expire, "
|
||||
"you will be automatically returned to the place where you have found it. "
|
||||
"Extra Orbs of Recall delay this without changing the recall location. "
|
||||
"Pick up an Orb of Safety causes an immediate recall."},
|
||||
{ ']', 0x8080FF, "Dodecahedron",
|
||||
"These dodecahedra made of a mysterious material are the Reptiles' favorite toy."
|
||||
},
|
||||
{ 'o', 0x8080FF, "Orb of Vaulting",
|
||||
"This Orb allows you to jump over an adjacent monster, killing or stunning it. "
|
||||
"You can only vault in a roughly straight line. "
|
||||
"Target a cell on the other side to use it."
|
||||
},
|
||||
{ '$', 0x80FF80, "Green Grass", prairiedesc },
|
||||
{ 'o', 0x8080FF, "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",
|
||||
"You get the powers of Shield, Horns, and Thorns after you move two moves in a straight line "
|
||||
"with this Orb." },
|
||||
{ '$', 0xC060C0, "Spinel", bulldashdesc },
|
||||
};
|
||||
|
||||
enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBone, itHell, itStatue,
|
||||
|
@ -1000,32 +1160,43 @@ enum eItem { itNone, itDiamond, itGold, itSpice, itRuby, itElixir, itShard, itBo
|
|||
itOrbLightning, itOrbFlash, itOrbWinter, itOrbSpeed, itOrbLife, itOrbShield, itOrbDigging,
|
||||
itOrbTeleport, itOrbSafety,
|
||||
itOrbThorns, itFernFlower,
|
||||
itWine, itOrbGhost, itSilver, itOrbPsi,
|
||||
itWine, itOrbAether, itSilver, itOrbPsi,
|
||||
itRoyalJelly, itEmerald, itOrbInvis, itPower, itOrbFire,
|
||||
itHolyGrail, itGrimoire,
|
||||
itOrbDragon, itOrbIllusion,
|
||||
itPirate, itCompass,
|
||||
itRedGem, itOrbPreserve, itOrbTelekinesis,
|
||||
itRedGem, itOrbTime, itOrbSpace,
|
||||
itBombEgg, itCoast, itWhirlpool,
|
||||
itOrbFriend, itOrbWater, itOrbAir,
|
||||
itPalace, itOrbFrog,
|
||||
itFjord, itOrbFish,
|
||||
itOrbDiscord,
|
||||
itSavedPrincess, itOrbLove,
|
||||
itEdge, itZebra,
|
||||
itIvory, itZebra,
|
||||
itFireShard, itAirShard, itEarthShard, itWaterShard,
|
||||
itElemental, itOrbSummon, itOrbMatter,
|
||||
itBounty, itRevolver, itFulgurite, itMutant,
|
||||
itOrbStunning, itOrbLuck,
|
||||
itMutant2, itOrbFreedom, itLotus, itOrbUndeath,
|
||||
itWindstone, itOrbEmpathy, itStrongWind, itBuggy, itBuggy2,
|
||||
itRose, itCoral, itOrbSkunk, itOrb37, itOrbEnergy,
|
||||
itBabyTortoise, itOrbShell, itApple, itDragon, itOrbDomination
|
||||
itRose, itCoral, itOrbBeauty, itOrb37, itOrbEnergy,
|
||||
itBabyTortoise, itOrbShell, itApple, itDragon, itOrbDomination,
|
||||
itOrbSword,
|
||||
itKraken, itOrbSword2, itBarrow,
|
||||
itTrollEgg, itWarning,
|
||||
itOrbStone, itOrbNature, itTreat,
|
||||
itSlime, itAmethyst,
|
||||
itOrbRecall, itDodeca,
|
||||
itOrbDash,
|
||||
itGreenGrass,
|
||||
itOrbHorns,
|
||||
itOrbBull,
|
||||
itBull
|
||||
};
|
||||
|
||||
// --- wall types ---
|
||||
|
||||
const int walltypes = 88;
|
||||
const int walltypes = 96;
|
||||
|
||||
struct walltype {
|
||||
char glyph;
|
||||
|
@ -1105,7 +1276,7 @@ walltype winf[walltypes] = {
|
|||
"using an Orb of Aether, your Aether power will be completely drained."
|
||||
},
|
||||
{ '#', 0xC0C0C0, "wall of Camelot", camelothelp },
|
||||
{ '#', 0xA06000, "Round Table", camelothelp },
|
||||
{ '+', 0xA06000, "Round Table", camelothelp },
|
||||
{ '=', 0x0000A0, "moat of Camelot", camelothelp},
|
||||
{ '+', 0x606060, "big statue of Cthulhu",
|
||||
"These statues of Cthulhu are too large to carry, and they don't look too "
|
||||
|
@ -1168,7 +1339,7 @@ walltype winf[walltypes] = {
|
|||
{ '#', 0x3030FF, "charged wall", elecdesc},
|
||||
{ '#', 0xFF3030, "grounded wall", elecdesc},
|
||||
{ '#', 0xA0A060, "sandstone wall", elecdesc},
|
||||
{ '+', 0x704000, "saloon wall", wildwestdesc},
|
||||
{ '#', 0x704000, "saloon wall", wildwestdesc},
|
||||
{ '#', 0x90C0C0, "metal wall", elecdesc},
|
||||
{ '#', 0x607030, "dead troll", trollhelpX},
|
||||
{ '+', 0xC0C0FF, "fan", winddesc},
|
||||
|
@ -1182,13 +1353,28 @@ walltype winf[walltypes] = {
|
|||
{ '#', 0xC0C000, "warp gate",
|
||||
"This gate separates the warped area from the normal land."},
|
||||
{ '+', 0x804000, "trunk", "The skeleton of a tree."},
|
||||
{ '+', 0x804000, "solid branch", "Branches here could bear your weight easily."},
|
||||
{ '+', 0x804000, "weak branch",
|
||||
{ '-', 0x402000, "solid branch", "Branches here could bear your weight easily."},
|
||||
{ ':', 0x804000, "weak branch",
|
||||
"Branches here will bear you weight, but if you use them to move (not fall) to an unstable place, they will break."},
|
||||
{ '+', 0x60C060, "canopy",
|
||||
"Only thin twigs and leaves here. They may bear fruits, but for you, these cells count "
|
||||
"as unstable."
|
||||
}
|
||||
},
|
||||
{ '#', 0xD0C060, "barrow wall", "This wall is quite strong. You will need another way in."},
|
||||
{ '#', 0x90A060, "barrow", "Your Orb of the Sword can be used to dig here."},
|
||||
{ '#', 0xE0E0E0, "stone statue", "A petrified creature."},
|
||||
{ '.', 0xE8E8E8, "tower of Camelot", camelothelp},
|
||||
{ '-', 0x402000, "big bush",
|
||||
"You can hold this bush to climb the Lost Mountain. "
|
||||
"Bushes block the movement of birds."
|
||||
},
|
||||
{ ':', 0x804000, "small bush",
|
||||
"You can hold this bush to climb the Lost Mountain, "
|
||||
"but it is not very strong -- it will get destroyed "
|
||||
"if you climb from it into an unstable location. "
|
||||
"Bushes block the movement of birds."},
|
||||
{ '.', 0xFFFF00, "Reptile floor", reptiledesc},
|
||||
{ '.', 0xFFFF00, "Reptile bridge", reptiledesc},
|
||||
};
|
||||
|
||||
enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCavefloor, waDeadTroll, waDune,
|
||||
|
@ -1212,12 +1398,16 @@ enum eWall { waNone, waIcewall, waBarrier, waFloorA, waFloorB, waCavewall, waCav
|
|||
waDeadTroll2, waFan,
|
||||
waTemporary, waEarthD, waElementalTmp, waElementalD,
|
||||
waFloorC, waFloorD, waRose, waWarpGate,
|
||||
waTrunk, waSolidBranch, waWeakBranch, waCanopy
|
||||
waTrunk, waSolidBranch, waWeakBranch, waCanopy,
|
||||
waBarrowWall, waBarrowDig,
|
||||
waPetrified, waTower,
|
||||
waBigBush, waSmallBush,
|
||||
waReptile, waReptileBridge
|
||||
};
|
||||
|
||||
// --- land types ---
|
||||
|
||||
const int landtypes = 56;
|
||||
const int landtypes = 67;
|
||||
|
||||
struct landtype {
|
||||
int color;
|
||||
|
@ -1355,6 +1545,42 @@ landtype linf[landtypes] = {
|
|||
},
|
||||
{ 0x487830, "Galápagos", tortoisedesc},
|
||||
{ 0xD04000, "Dragon Chasms", dragondesc},
|
||||
{ 0xD04000, "Kraken Depths",
|
||||
"A long time ago, this was a trade route. But then, Krakens have risen out of the "
|
||||
"depths. Many trading ships sank here. Legend says that you can uncover the secret "
|
||||
"of a magical weapon spell somewhere in the depths...\n\n"
|
||||
|
||||
"You can find Sunken Treasures here, but they won't appear until you have killed "
|
||||
"a Kraken. You will also need Orb of the Fish to get the treasures, luckily you can "
|
||||
"steal one from the Viking treasure hunters."
|
||||
},
|
||||
{ 0x804020, "Burial Grounds",
|
||||
"Ancient Viking heroes were buried here. Their graves have barrows raised over "
|
||||
"them, and are guarded by Draugar, animated corpses who are immune to mundane weapons. "
|
||||
"You will need to use a magical weapon spell to defeat them, and to rob the "
|
||||
"ancient jewelry buried in the graves."
|
||||
},
|
||||
{ 0x90A548, "Trollheim",
|
||||
"Many clans of Trolls spend their lives in this kingdom. You can find many "
|
||||
"statues of Trolls here. You suppose that they are not actually statues, but simply "
|
||||
"elderly Trolls, who have petrified upon death. Or maybe you have killed "
|
||||
"these Trolls yourself?"
|
||||
},
|
||||
{ 0xFF7518, "Halloween", halloweendesc},
|
||||
{ 0x605040, "Dungeon",
|
||||
"The result of a collaboration of the Great Vizier and the Wizard of the Ivory Tower."
|
||||
},
|
||||
{ 0x603000, "Lost Mountain",
|
||||
"Gravitational anomalies in the Jungle create mountains "
|
||||
"overgrown with ivies and bushes. "
|
||||
"Will you dare to climb the ivies to get the amethysts hidden above?\n\n"
|
||||
"Cells adjacent to Ivies count as stable (but Ivies "
|
||||
"cannot climb themselves or other Ivies)."},
|
||||
{ 0xFFFF00, "Reptiles", reptiledesc},
|
||||
{ 0x0000D0, "Prairie", prairiedesc},
|
||||
{ 0x800080, "Bull Dash", bulldashdesc},
|
||||
{ 0xC000C0, "Crossroads V", "Extremely narrow Crossroads layout.\n"},
|
||||
{ 0xC0C0C0, "Cellular Automaton", cadesc}
|
||||
};
|
||||
|
||||
enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle, laAlchemist, laMirror, laGraveyard,
|
||||
|
@ -1367,8 +1593,11 @@ enum eLand { laNone, laBarrier, laCrossroads, laDesert, laIce, laCaves, laJungle
|
|||
laCanvas, laPrincessQuest,
|
||||
laWildWest, laStorms, laOvergrown, laClearing,
|
||||
laHaunted, laHauntedWall, laHauntedBorder,
|
||||
laWhirlwind, laRose, laGridCoast, laGridSea, laCrossroads4,
|
||||
laEndorian, laTortoise, laDragon
|
||||
laWhirlwind, laRose, laWarpCoast, laWarpSea, laCrossroads4,
|
||||
laEndorian, laTortoise, laDragon,
|
||||
laKraken, laBurial, laTrollheim,
|
||||
laHalloween, laDungeon, laMountain, laReptile,
|
||||
laPrairie, laBull, laCrossroads5, laCA
|
||||
};
|
||||
|
||||
// cell information for the game
|
||||
|
@ -1387,69 +1616,104 @@ struct gcell {
|
|||
unsigned ligon : 1; // is it sparkling with lightning?
|
||||
|
||||
unsigned
|
||||
pathdist : 5, // player distance wrt usual movement
|
||||
pathdist : 7, // player distance wrt usual movement
|
||||
cpdist : 5, mpdist : 5; // current/minimum player distance
|
||||
|
||||
unsigned mondir : 3, // monster direction, for multi-tile monsters and graphics
|
||||
bardir : 4, // barrier direction
|
||||
stuntime : 4, // stun time left (for Palace Guards and Skeletons)
|
||||
hitpoints : 3, // hitpoints left (for Palace Guards)
|
||||
landflags : 2; // extra flags for land
|
||||
hitpoints : 3; // hitpoints left (for Palace Guards, also reused as cpid for mirrors)
|
||||
|
||||
unsigned landflags : 8; // extra flags for land
|
||||
|
||||
char wparam; // wall parameter, used for remaining power of Bonfires and Thumpers
|
||||
|
||||
// 'tmp' is used for:
|
||||
// pathfinding algorithm used by monsters with atypical movement (which do not use pathdist)
|
||||
// bugs' pathfinding algorithm
|
||||
short aitmp;
|
||||
|
||||
// 'landparam' is used for:
|
||||
// heat in Icy/Cocytus;
|
||||
// heat in Dry (0..10);
|
||||
// CR2 structure;
|
||||
// hive Weird Rock color / pheromones;
|
||||
// Ocean/coast depth
|
||||
union { int32_t landpar; float heat; char bytes[4]; } LHU;
|
||||
// Ocean/coast depth;
|
||||
// Bomberbird Egg hatch time / mine marking;
|
||||
// number of Ancient Jewelry;
|
||||
// improved tracking in Trollheim
|
||||
union {
|
||||
int32_t landpar;
|
||||
float heat;
|
||||
char bytes[4];
|
||||
struct fieldinfo {
|
||||
uint16_t fieldval;
|
||||
unsigned rval : 4;
|
||||
unsigned flowerdist : 4;
|
||||
unsigned walldist : 4;
|
||||
unsigned walldist2 : 4;
|
||||
} fi;
|
||||
|
||||
} LHU;
|
||||
};
|
||||
|
||||
#define landparam LHU.landpar
|
||||
|
||||
#define fval LHU.fi.fieldval
|
||||
|
||||
#define NODIR 7
|
||||
#define NOBARRIERS 8
|
||||
|
||||
#define LAND_OVER 44
|
||||
eLand land_over[LAND_OVER] = {
|
||||
#define LAND_OVER 53
|
||||
#define LAND_OVERX 55
|
||||
|
||||
eLand land_over[LAND_OVERX] = {
|
||||
laIce, laCaves, laDesert, laMotion, laJungle, laAlchemist,
|
||||
laCrossroads,
|
||||
laMirror, laMinefield, laZebra, laPalace, laPrincessQuest,
|
||||
laOcean, laLivefjord, laGridCoast, laCaribbean, laWhirlpool, laRlyeh, laTemple,
|
||||
laMirror, laMinefield, laPalace, laPrincessQuest, laZebra, laReptile,
|
||||
laOcean, laWarpCoast, laLivefjord, laKraken, laCaribbean, laWhirlpool, laRlyeh, laTemple,
|
||||
laIvoryTower, laEndorian, laDungeon, laMountain,
|
||||
laCrossroads2,
|
||||
laDryForest, laWineyard, laDeadCaves, laGraveyard, laHaunted, laHive,
|
||||
laRedRock,
|
||||
laIvoryTower, laEndorian,
|
||||
laDragon, laTortoise,
|
||||
laOvergrown, laClearing, laStorms, laWhirlwind, laRose,
|
||||
laEmerald, laCamelot, laElementalWall,
|
||||
laHell, laCrossroads3, laCocytus, laPower, laCrossroads4
|
||||
laOvergrown, laClearing, laStorms, laWhirlwind, laRose, laBurial,
|
||||
laEmerald, laCamelot,
|
||||
laPrairie, laBull,
|
||||
laElementalWall, laTrollheim,
|
||||
laHell, laCrossroads3, laCocytus, laPower, laCrossroads4,
|
||||
laCrossroads5,
|
||||
// EXTRA
|
||||
laWildWest, laHalloween
|
||||
};
|
||||
|
||||
#define LAND_EUC 42
|
||||
#define LAND_EUC 49
|
||||
eLand land_euc[LAND_EUC] = {
|
||||
laIce, laCaves, laDesert, laMotion, laJungle,
|
||||
laCrossroads,
|
||||
laMirror, laMinefield, laAlchemist, laZebra, laPalace, laPrincessQuest,
|
||||
laOcean, laLivefjord, laGridCoast, laCaribbean, laWhirlpool, laRlyeh, laTemple,
|
||||
laElementalWall,
|
||||
laOcean, laLivefjord, laWarpCoast, laCaribbean, laKraken, laWhirlpool, laRlyeh, laTemple,
|
||||
laElementalWall, laTrollheim,
|
||||
laDryForest, laWineyard, laDeadCaves, laGraveyard, laHive, laRedRock, laIvoryTower,
|
||||
laOvergrown, laClearing, laStorms, laWhirlwind, laRose,
|
||||
laOvergrown, laClearing, laStorms, laWhirlwind, laRose, laBurial,
|
||||
laEmerald, laCamelot, laDragon, laTortoise,
|
||||
laHell, laCrossroads3, laCocytus, laPower,
|
||||
laCrossroads4,
|
||||
laWildWest
|
||||
laWildWest,
|
||||
laReptile, laMountain, laBull, laPrairie
|
||||
};
|
||||
// MISSING: laCrossroads2
|
||||
|
||||
#define LAND_HYP 39
|
||||
#define LAND_SPH 39
|
||||
eLand land_sph[LAND_SPH] = {
|
||||
laHalloween,
|
||||
laIce, laCaves, laDesert, laMotion, laJungle,
|
||||
laCrossroads,
|
||||
laMirror, laMinefield, laAlchemist,
|
||||
laLivefjord, laWarpCoast, laKraken, laRlyeh,
|
||||
laTrollheim,
|
||||
laDryForest, laDeadCaves, laGraveyard, laHive, laRedRock,
|
||||
laOvergrown, laStorms, laWhirlwind, laRose, laBurial,
|
||||
laEmerald, laDragon, laTortoise,
|
||||
laHell, laCrossroads3, laCocytus, laPower, laElementalWall,
|
||||
laCrossroads4,
|
||||
laWildWest, laPalace, laBull, laPrairie, laCA
|
||||
};
|
||||
|
||||
#define LAND_HYP 47
|
||||
eLand land_hyp[LAND_HYP] = {
|
||||
laHell, laCocytus, laGraveyard,
|
||||
laWineyard, laDryForest, laCaves,
|
||||
|
@ -1458,8 +1722,14 @@ eLand land_hyp[LAND_HYP] = {
|
|||
laDesert, laRedRock,
|
||||
laWhirlpool, laOvergrown, laClearing, laStorms,
|
||||
laCaribbean, laJungle, laAlchemist, laMotion, laMirror, laMinefield,
|
||||
laZebra, laElementalWall, laIvoryTower, laHaunted, laWhirlwind, laCrossroads,
|
||||
laGridCoast, laRose, laDragon, laEndorian, laTortoise
|
||||
laZebra, laElementalWall, laIvoryTower, laHaunted, laWhirlwind,
|
||||
laWarpCoast, laRose, laDragon, laEndorian,
|
||||
laReptile, laDungeon, laMountain,
|
||||
laTortoise,
|
||||
laKraken, laBurial, laTrollheim,
|
||||
laPrairie, laBull,
|
||||
// always must be last
|
||||
laCrossroads
|
||||
};
|
||||
|
||||
#define LAND_SCAPE 32
|
||||
|
@ -1472,29 +1742,32 @@ eLand land_scape[LAND_SCAPE] = {
|
|||
laOvergrown, laStorms,
|
||||
laJungle, laAlchemist, laMotion, laMirror, laMinefield,
|
||||
laZebra, laWhirlwind, laCrossroads,
|
||||
laGridCoast, laRose,
|
||||
laWarpCoast, laRose,
|
||||
laCrossroads, laCrossroads2, laCrossroads3
|
||||
};
|
||||
|
||||
#define LAND_TAC 44
|
||||
#define LAND_TAC 50
|
||||
|
||||
struct landtacinfo { eLand l; int tries, multiplier; };
|
||||
|
||||
landtacinfo land_tac[LAND_TAC] = {
|
||||
{laIce, 10, 1}, {laDesert, 10, 1}, {laMotion, 10, 1}, {laCaves, 10, 1}, {laAlchemist, 10, 1},
|
||||
{laJungle, 10, 1}, {laMirror, 10, 1}, {laZebra, 10, 1}, {laPalace, 10, 1},
|
||||
{laOcean, 10, 1}, {laLivefjord, 10, 1}, {laGridCoast, 10, 1}, {laRlyeh, 10, 1}, {laHell, 10, 1},
|
||||
{laElementalWall, 10, 1}, {laDryForest, 10, 1}, {laWineyard, 10, 1},
|
||||
{laOcean, 10, 1}, {laLivefjord, 10, 1}, {laWarpCoast, 10, 1}, {laRlyeh, 10, 1}, {laHell, 10, 1},
|
||||
{laDryForest, 10, 1}, {laWineyard, 10, 1}, {laReptile, 10, 1},
|
||||
{laDeadCaves, 10, 1}, {laGraveyard, 10, 1},
|
||||
{laHaunted, 10, 1},
|
||||
{laIvoryTower, 10, 1}, {laEndorian, 10, 1},
|
||||
{laIvoryTower, 10, 1}, {laEndorian, 10, 1}, {laMountain, 5, 2}, {laDungeon, 5, 2},
|
||||
{laEmerald, 10, 1},
|
||||
{laCocytus, 10, 1},
|
||||
|
||||
{laCaribbean, 5, 2}, {laWhirlpool, 5, 2}, {laTemple, 5, 2}, {laMinefield, 5, 2},
|
||||
{laCaribbean, 5, 2}, {laWhirlpool, 5, 2}, {laKraken, 5, 2},
|
||||
{laTemple, 5, 2}, {laMinefield, 5, 2},
|
||||
{laPower, 5, 2}, {laHive, 5, 2}, {laRedRock, 5, 2}, {laStorms, 5, 2}, {laOvergrown, 5, 2},
|
||||
{laClearing, 5, 2},
|
||||
{laWhirlwind, 5, 2}, {laRose, 5, 2}, {laDragon, 2, 5}, {laTortoise, 1, 10},
|
||||
{laBurial, 5, 2},
|
||||
{laElementalWall, 10, 1}, {laTrollheim, 5, 2},
|
||||
|
||||
{laCrossroads, 10, 1}, {laCrossroads2, 10, 1}, {laCrossroads3, 10, 1}, {laCrossroads4, 10, 1},
|
||||
|
||||
|
@ -1506,6 +1779,6 @@ landtacinfo land_tac[LAND_TAC] = {
|
|||
eLand randlands[RANDLANDS] = {
|
||||
laIce, laDesert, laCaves, laAlchemist, laGraveyard, laPower, laLivefjord, laZebra,
|
||||
laRlyeh, laDryForest, laEmerald, laWineyard, laDeadCaves, laRedRock,
|
||||
laOvergrown, laWildWest, laGridCoast
|
||||
laOvergrown, laWildWest, laWarpCoast
|
||||
};
|
||||
|
||||
|
|
831
complex.cpp
831
complex.cpp
File diff suppressed because it is too large
Load Diff
181
conformal.cpp
181
conformal.cpp
|
@ -4,11 +4,10 @@
|
|||
|
||||
namespace polygonal {
|
||||
|
||||
typedef long double ld;
|
||||
typedef complex<long double> cld;
|
||||
typedef complex<ld> cld;
|
||||
|
||||
int SI = 4;
|
||||
double STAR = 0;
|
||||
ld STAR = 0;
|
||||
|
||||
int deg = 20;
|
||||
|
||||
|
@ -55,7 +54,7 @@ namespace polygonal {
|
|||
}
|
||||
|
||||
pair<ld, ld> compute(ld x, ld y, int prec) {
|
||||
if(pmodel == 4) {
|
||||
if(pmodel == mdPolynomial) {
|
||||
cld z(x,y);
|
||||
cld res (0,0);
|
||||
for(int i=maxcoef; i>=0; i--) { res += coef[i]; if(i) res *= z; }
|
||||
|
@ -77,28 +76,21 @@ namespace polygonal {
|
|||
pair<ld, ld> compute(ld x, ld y) { return compute(x,y,deg); }
|
||||
|
||||
void drawBoundary(int color) {
|
||||
#ifdef GL
|
||||
if(vid.usingGL) {
|
||||
qglcoords = 0;
|
||||
glcolor(color);
|
||||
int pts = 0;
|
||||
for(int r=0; r<2000; r++) {
|
||||
cld z = exp(cld(0, 2*M_PI * r / 2000.0));
|
||||
pair<ld,ld> z2 = compute(real(z), imag(z), deg);
|
||||
glcoords[pts][0] = vid.radius * z2.first;
|
||||
glcoords[pts][1] = vid.radius * z2.second;
|
||||
glcoords[pts][2] = vid.scrdist;
|
||||
pts++;
|
||||
}
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, glcoords);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, pts);
|
||||
return;
|
||||
queuereset(mdDisk, PPR_CIRCLE);
|
||||
|
||||
for(int r=0; r<=2000; r++) {
|
||||
cld z = exp(cld(0, 2*M_PI * r / 2000.0));
|
||||
pair<ld,ld> z2 = compute(real(z), imag(z), deg);
|
||||
hyperpoint h;
|
||||
h[0] = z2.first * vid.radius;
|
||||
h[1] = z2.second * vid.radius;
|
||||
h[2] = vid.scrdist;
|
||||
curvepoint(h);
|
||||
}
|
||||
#endif
|
||||
|
||||
queuecurve(color, 0, PPR_CIRCLE);
|
||||
queuereset(pmodel, PPR_CIRCLE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -247,7 +239,7 @@ namespace conformal {
|
|||
vector<cell*> movehistory;
|
||||
|
||||
bool includeHistory;
|
||||
double lvspeed = 1;
|
||||
ld lvspeed = 1;
|
||||
int bandhalf = 200;
|
||||
int bandsegment = 16000;
|
||||
int rotation = 0;
|
||||
|
@ -368,10 +360,9 @@ namespace conformal {
|
|||
shmup::calc_relative_matrix(v[j+1]->base, v[j]->base->master) *
|
||||
v[j+1]->at * C0;
|
||||
|
||||
int x, y, shift;
|
||||
getcoord(next, x, y, shift);
|
||||
|
||||
tpixels += x-vid.xcenter;
|
||||
hyperpoint nextscr;
|
||||
applymodel(next, nextscr);
|
||||
tpixels += nextscr[0] * vid.radius;
|
||||
}
|
||||
|
||||
vid.radius = rad;
|
||||
|
@ -447,7 +438,7 @@ namespace conformal {
|
|||
v[j+1]->at * C0;
|
||||
|
||||
int x, y, shift;
|
||||
getcoord(next, x, y, shift);
|
||||
getcoord0(next, x, y, shift);
|
||||
|
||||
int bwidth = x-bandhalf;
|
||||
|
||||
|
@ -489,62 +480,83 @@ namespace conformal {
|
|||
}
|
||||
#endif
|
||||
|
||||
const char* directions[5][4] = {
|
||||
const char* directions[MODELCOUNT][4] = {
|
||||
{ "right", "up", "left", "down" },
|
||||
{ "counterclockwise", "zoom out", "clockwise", "zoom in" },
|
||||
{ "left to right", "spin down", "right to left", "spin up" },
|
||||
{ "right", "up", "left", "down" },
|
||||
{ "right", "up", "left", "down" },
|
||||
{ "right", "up", "left", "down" },
|
||||
{ "right", "up", "left", "down" },
|
||||
{ "right", "up", "left", "down" },
|
||||
{ "right", "up", "left", "down" }
|
||||
};
|
||||
|
||||
const char *modelnames[5] = {
|
||||
"disk", "half-plane", "band", "polygonal", "polynomial"
|
||||
const char *modelnames[MODELCOUNT] = {
|
||||
"disk", "half-plane", "band", "polygonal", "polynomial",
|
||||
"azimuthal equidistant", "azimuthal equi-area",
|
||||
"ball model", "hyperboloid"
|
||||
};
|
||||
|
||||
void show() {
|
||||
displayStat( 0, XLAT("conformal/history mode"), "", ' ');
|
||||
dialog::init(XLAT("conformal/history mode"));
|
||||
|
||||
displayStat( 2, XLAT("include history"), ONOFF(includeHistory), 'i');
|
||||
dialog::addBoolItem(XLAT("include history"), (includeHistory), 'i');
|
||||
|
||||
bool notconformal = (pmodel >= 5 && pmodel <= 6) || abs(vid.alpha-1) > 1e-3;
|
||||
|
||||
displayStat( 4, XLAT("model used"), modelnames[pmodel], 'm');
|
||||
displayStat( 5, XLAT("rotation"), directions[pmodel][rotation&3], 'r');
|
||||
dialog::addSelItem(notconformal ? XLAT("model used (not conformal!)") : XLAT("model used"), XLAT(modelnames[pmodel]), 'm');
|
||||
dialog::addSelItem(XLAT("rotation"), directions[pmodel][rotation&3], 'r');
|
||||
|
||||
if(pmodel == 4) {
|
||||
displayStat( 6, XLAT("coefficient"),
|
||||
fts4(real(polygonal::coef[polygonal::coefid]))+"+"+
|
||||
fts4(imag(polygonal::coef[polygonal::coefid]))+"i", 'x');
|
||||
displayStat( 7, XLAT("which coefficient"), its(polygonal::coefid), 'n');
|
||||
dialog::addSelItem(XLAT("coefficient"),
|
||||
fts4(real(polygonal::coef[polygonal::coefid])), 'x');
|
||||
dialog::addSelItem(XLAT("coefficient (imaginary)"),
|
||||
fts4(imag(polygonal::coef[polygonal::coefid])), 'y');
|
||||
dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n');
|
||||
}
|
||||
|
||||
if(pmodel == 3) {
|
||||
displayStat( 6, XLAT("polygon sides"), its(polygonal::SI), 'x');
|
||||
displayStat( 7, XLAT("star factor"), fts(polygonal::STAR), 'y');
|
||||
displayStat( 8, XLAT("degree of the approximation"), its(polygonal::deg), 'n');
|
||||
dialog::addSelItem(XLAT("polygon sides"), its(polygonal::SI), 'x');
|
||||
dialog::addSelItem(XLAT("star factor"), fts(polygonal::STAR), 'y');
|
||||
dialog::addSelItem(XLAT("degree of the approximation"), its(polygonal::deg), 'n');
|
||||
}
|
||||
|
||||
displayStat(10, XLAT("prepare the line animation"), ONOFF(on), 'e');
|
||||
if(on) displayStat(11, XLAT("animation speed"), fts(lvspeed), 'a');
|
||||
dialog::addBoolItem(XLAT("prepare the line animation"), (on), 'e');
|
||||
if(on) dialog::addSelItem(XLAT("animation speed"), fts(lvspeed), 'a');
|
||||
|
||||
#ifndef MOBILE
|
||||
displayStat(13, XLAT("render bands automatically"), ONOFF(autoband), 'o');
|
||||
dialog::addBoolItem(XLAT("render bands automatically"), (autoband), 'o');
|
||||
if(autoband)
|
||||
displayStat(14, XLAT("include history when auto-rendering"), ONOFF(autobandhistory), 'j');
|
||||
dialog::addBoolItem(XLAT("include history when auto-rendering"), (autobandhistory), 'j');
|
||||
|
||||
bool renderable = on && pmodel == 2;
|
||||
if(renderable || autoband) {
|
||||
displayStat(15, XLAT("band width"), its(bandhalf*2), 'd');
|
||||
displayStat(16, XLAT("length of a segment"), its(bandsegment), 's');
|
||||
displayStat(17, XLAT("spiral on rendering"), ONOFF(dospiral), 'g');
|
||||
dialog::addSelItem(XLAT("band width"), "2*"+its(bandhalf), 'd');
|
||||
dialog::addSelItem(XLAT("length of a segment"), its(bandsegment), 's');
|
||||
dialog::addBoolItem(XLAT("spiral on rendering"), (dospiral), 'g');
|
||||
if(renderable)
|
||||
displayStat(18, XLAT("render now (length: %1)", its(measureLength())), "", 'f');
|
||||
dialog::addItem(XLAT("render now (length: %1)", its(measureLength())), 'f');
|
||||
}
|
||||
#endif
|
||||
|
||||
displayStat(20, XLAT("exit this menu"), "", 'q');
|
||||
dialog::addItem(XLAT("exit this menu"), 'q');
|
||||
dialog::display();
|
||||
mouseovers = XLAT("see http://www.roguetemple.com/z/hyper/conformal.php");
|
||||
}
|
||||
|
||||
void handleKey(int uni, int sym) {
|
||||
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 handleKey(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
ib = 0;
|
||||
|
||||
if(uni == 'e') {
|
||||
if(on) clear();
|
||||
|
@ -559,38 +571,53 @@ namespace conformal {
|
|||
}
|
||||
else if(uni == 'o')
|
||||
autoband = !autoband;
|
||||
else if(uni == 'm') {
|
||||
pmodel++;
|
||||
pmodel %= 5;
|
||||
if(pmodel == 3) polygonal::solve();
|
||||
else if(uni == 'm' || uni == 'M') {
|
||||
|
||||
switchagain: {
|
||||
pmodel = eModel((pmodel + (shiftmul > 0 ? 1 : -1) + MODELCOUNT) % MODELCOUNT);
|
||||
if(sphere)
|
||||
if(pmodel == mdHalfplane || pmodel == mdBand || pmodel == mdEquidistant || pmodel == mdEquiarea)
|
||||
goto switchagain;
|
||||
}
|
||||
if(pmodel == mdPolygonal) polygonal::solve();
|
||||
/* if(pmodel && vid.usingGL) {
|
||||
addMessage(XLAT("openGL mode disabled"));
|
||||
vid.usingGL = false;
|
||||
setvideomode();
|
||||
} */
|
||||
}
|
||||
else if(sym == 'x' && pmodel == 3) { polygonal::SI += (shiftmul > 0 ? 1:-1); polygonal::solve(); }
|
||||
else if(sym == 'y' && pmodel == 3) { polygonal::STAR += shiftmul/10; polygonal::solve(); }
|
||||
else if(sym == 'n' && pmodel == 3) { polygonal::deg += (shiftmul>0?1:-1);
|
||||
if(polygonal::deg < 2) polygonal::deg = 2;
|
||||
if(polygonal::deg > MSI-1) polygonal::deg = MSI-1;
|
||||
else if(sym == 'x' && pmodel == mdPolygonal)
|
||||
dialog::editNumber(polygonal::SI, 3, 10, 1, 4, XLAT("polygon sides"), "");
|
||||
else if(sym == 'y' && pmodel == mdPolygonal)
|
||||
dialog::editNumber(polygonal::STAR, -1, 1, .1, 0, XLAT("star factor"), "");
|
||||
else if(sym == 'n' && pmodel == mdPolygonal)
|
||||
dialog::editNumber(polygonal::deg, 2, MSI-1, 1, 2, XLAT("degree of the approximation"), "");
|
||||
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;
|
||||
}
|
||||
else if(sym == 'x' && pmodel == 4) {
|
||||
int ci = polygonal::coefid;
|
||||
polygonal::coef[polygonal::coefid] += polygonal::cld(shiftmul/100/ci/ci, 0);
|
||||
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;
|
||||
}
|
||||
else if(sym == 'y' && pmodel == 4) {
|
||||
int ci = polygonal::coefid;
|
||||
polygonal::coef[polygonal::coefid] += polygonal::cld(0, shiftmul/100/ci/ci);
|
||||
}
|
||||
else if(sym == 'n' && pmodel == 4) { polygonal::coefid += (shiftmul>0?1:-1); polygonal::maxcoef = max(polygonal::maxcoef, polygonal::coefid); }
|
||||
else if(sym == 'n' && pmodel == mdPolynomial)
|
||||
dialog::editNumber(polygonal::coefid, 0, MSI-1, 1, 0, XLAT("which coefficient"), "");
|
||||
else if(sym == 'r') rotation += (shiftmul > 0 ? 1:3);
|
||||
else if(sym == 'a') { lvspeed += shiftmul/10; }
|
||||
else if(sym == 'd') { bandhalf += int(5 * shiftmul); if(bandhalf < 5) bandhalf = 5; }
|
||||
else if(sym == 's') { bandsegment += int(500 * shiftmul); if(bandsegment < 500) bandsegment = 500; }
|
||||
else if(sym == 'a')
|
||||
dialog::editNumber(lvspeed, -5, 5, .1, 1, XLAT("animation speed"), "");
|
||||
else if(sym == 'd')
|
||||
dialog::editNumber(bandhalf, 5, 1000, 5, 200, XLAT("band width"), "");
|
||||
else if(sym == 's')
|
||||
dialog::editNumber(bandsegment, 500, 32000, 500, 16000, XLAT("band segment"), "");
|
||||
else if(sym == 'g') { dospiral = !dospiral; }
|
||||
#ifndef MOBILE
|
||||
else if(uni == 'f' && pmodel == 2 && on) createImage(dospiral);
|
||||
else if(uni == 'f' && pmodel == mdBand && on) createImage(dospiral);
|
||||
#endif
|
||||
else if(sym == 'q' || sym == SDLK_ESCAPE || sym == '0') { cmode = emNormal; }
|
||||
else if(sym == 'i') {
|
||||
|
@ -646,10 +673,10 @@ namespace conformal {
|
|||
#ifndef MOBILE
|
||||
if(celldist(cwt.c) <= 7) return;
|
||||
if(!autoband) return;
|
||||
int spm = pmodel;
|
||||
eModel spm = pmodel;
|
||||
bool ih = includeHistory;
|
||||
includeHistory = autobandhistory;
|
||||
pmodel = 2;
|
||||
pmodel = mdBand;
|
||||
create();
|
||||
createImage(dospiral);
|
||||
clear();
|
||||
|
|
|
@ -0,0 +1,727 @@
|
|||
/* Missing.
|
||||
|
||||
#ifndef MOBILE
|
||||
dialog::addItemHelp(16, XLAT("use Shift to decrease and Ctrl to fine tune "));
|
||||
dialog::addItemHelp(17, XLAT("(e.g. Shift+Ctrl+Z)"));
|
||||
#endif
|
||||
|
||||
if(xuni == 'i') {
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
namespace dialog {
|
||||
|
||||
namespace zoom {
|
||||
int zoomf = 1, shiftx, shifty;
|
||||
bool zoomoff = false;
|
||||
};
|
||||
|
||||
#ifdef MENU_SCALING
|
||||
#ifndef MOBILE
|
||||
void handleZooming(SDL_Event &ev) {
|
||||
using namespace zoom;
|
||||
if(zoomoff || (cmode != emOverview && cmode != emTactic)) {
|
||||
zoomf = 1; shiftx = shifty = 0; zoomoff = false; return;
|
||||
}
|
||||
if(ev.type == SDL_MOUSEBUTTONDOWN) {
|
||||
zoomf = 3;
|
||||
}
|
||||
if(zoomf == 3) {
|
||||
shiftx = -2*mousex;
|
||||
shifty = -2*mousey;
|
||||
}
|
||||
if(ev.type == SDL_MOUSEBUTTONUP && zoomf > 1) {
|
||||
zoomoff = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
inline void handleZooming(SDL_Event &ev) {}
|
||||
#endif
|
||||
|
||||
bool displayzoom(int x, int y, int b, int size, const string &s, int color, int align) {
|
||||
using namespace zoom;
|
||||
return displayfr(x * zoomf + shiftx, y * zoomf + shifty, b, size * zoomf, s, color, align);
|
||||
}
|
||||
|
||||
vector<item> items;
|
||||
|
||||
item& lastItem() { return items[items.size() - 1]; }
|
||||
|
||||
void init() { items.clear(); }
|
||||
|
||||
string keyname(int k) {
|
||||
if(k == 0) return "";
|
||||
if(k == SDLK_ESCAPE) return "Esc";
|
||||
if(k == SDLK_F5) return "F5";
|
||||
if(k == SDLK_F10) return "F10";
|
||||
if(k == SDLK_HOME) return "Home";
|
||||
if(k == 32) return "space";
|
||||
if(k >= 1 && k <= 26) { string s = "Ctrl+"; s += (k+64); return s; }
|
||||
if(k < 128) { string s; s += k; return s; }
|
||||
return "?";
|
||||
}
|
||||
|
||||
void addSlider(double d1, double d2, double d3, int key) {
|
||||
item it;
|
||||
it.type = diSlider;
|
||||
it.color = 0xC0C0C0;
|
||||
it.scale = 100;
|
||||
it.key = key;
|
||||
it.param = (d2-d1) / (d3-d1);
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addSelItem(string body, string value, int key) {
|
||||
item it;
|
||||
it.type = diItem;
|
||||
it.body = body;
|
||||
it.value = value;
|
||||
it.keycaption = keyname(key);
|
||||
it.key = key;
|
||||
it.color = 0xC0C0C0;
|
||||
it.colork = 0x808080;
|
||||
it.colorv = 0x80A040;
|
||||
it.colors = 0xFFD500;
|
||||
it.colorc = 0xFFD500;
|
||||
it.colors = 0xFF8000;
|
||||
if(value == ONOFF(true)) it.colorv = 0x40FF40;
|
||||
if(value == ONOFF(false)) it.colorv = 0xC04040;
|
||||
it.scale = 100;
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addBoolItem(string body, bool value, int key) {
|
||||
addSelItem(body, ONOFF(value), key);
|
||||
}
|
||||
|
||||
void addColorItem(string body, int value, int key) {
|
||||
item it;
|
||||
it.type = diItem;
|
||||
it.body = body;
|
||||
it.value = COLORBAR;
|
||||
it.keycaption = keyname(key);
|
||||
it.key = key;
|
||||
it.color = it.colorv = value >> 8;
|
||||
it.colors = it.color ^ 0x404040;
|
||||
it.colorc = it.color ^ 0x808080;
|
||||
it.scale = 100;
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addHelp(string body) {
|
||||
item it;
|
||||
it.type = diHelp;
|
||||
it.body = body;
|
||||
it.scale = 100;
|
||||
|
||||
if(size(body) >= 500) it.scale = 70;
|
||||
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addInfo(string body, int color) {
|
||||
item it;
|
||||
it.type = diInfo;
|
||||
it.body = body;
|
||||
it.color = color;
|
||||
it.scale = 100;
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addItem(string body, int key) {
|
||||
item it;
|
||||
it.type = diItem;
|
||||
it.body = body;
|
||||
it.keycaption = keyname(key);
|
||||
it.key = key;
|
||||
it.color = 0xC0C0C0;
|
||||
it.colork = 0x808080;
|
||||
it.colors = 0xFFD500;
|
||||
it.colorc = 0xFF8000;
|
||||
it.scale = 100;
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addBreak(int val) {
|
||||
item it;
|
||||
it.type = diBreak;
|
||||
it.scale = val;
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void addTitle(string body, int color, int scale) {
|
||||
item it;
|
||||
it.type = diTitle;
|
||||
it.body = body;
|
||||
it.color = color;
|
||||
it.scale = scale;
|
||||
items.push_back(it);
|
||||
}
|
||||
|
||||
void init(string title, int color, int scale, int brk) {
|
||||
init();
|
||||
addTitle(title, color, scale);
|
||||
addBreak(brk);
|
||||
}
|
||||
|
||||
int displayLong(string str, int siz, int y, bool measure) {
|
||||
|
||||
int last = 0;
|
||||
int lastspace = 0;
|
||||
|
||||
int xs = vid.xres * 618/1000;
|
||||
int xo = vid.xres * 186/1000;
|
||||
|
||||
for(int i=0; i<=size(str); i++) {
|
||||
int ls = 0;
|
||||
int prev = last;
|
||||
if(str[i] == ' ') lastspace = i;
|
||||
if(textwidth(siz, str.substr(last, i-last)) > xs) {
|
||||
if(lastspace == last) ls = i-1, last = i-1;
|
||||
else ls = lastspace, last = ls+1;
|
||||
}
|
||||
if(str[i] == 10 || i == size(str)) ls = i, last = i+1;
|
||||
if(ls) {
|
||||
if(!measure) displayfr(xo, y, 2, siz, str.substr(prev, ls-prev), 0xC0C0C0, 0);
|
||||
if(ls == prev) y += siz/2;
|
||||
else y += siz;
|
||||
lastspace = last;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
y += siz/2;
|
||||
return y;
|
||||
}
|
||||
|
||||
int tothei, dialogwidth, dfsize, dfspace, leftwidth, rightwidth, innerwidth, itemx, keyx, valuex;
|
||||
|
||||
string highlight_text;
|
||||
|
||||
void measure() {
|
||||
tothei = 0;
|
||||
dialogwidth = 0;
|
||||
innerwidth = 0;
|
||||
int N = items.size();
|
||||
for(int i=0; i<N; i++) {
|
||||
if(items[i].type == diHelp)
|
||||
tothei += displayLong(items[i].body, dfsize * items[i].scale / 100, 0, true);
|
||||
else {
|
||||
tothei += dfspace * items[i].scale / 100;
|
||||
if(items[i].type == diItem)
|
||||
innerwidth = max(innerwidth, textwidth(dfsize * items[i].scale / 100, items[i].body));
|
||||
if(items[i].type == diTitle || items[i].type == diInfo)
|
||||
dialogwidth = max(dialogwidth, textwidth(dfsize * items[i].scale / 100, items[i].body) * 10/9);
|
||||
}
|
||||
}
|
||||
|
||||
leftwidth = ISMOBILE ? 0 : textwidth(dfsize, "MMMMM") + dfsize/2;
|
||||
rightwidth = textwidth(dfsize, "MMMMMMMM") + dfsize/2;
|
||||
|
||||
int fwidth = innerwidth + leftwidth + rightwidth;
|
||||
dialogwidth = max(dialogwidth, fwidth);
|
||||
itemx = (vid.xres - fwidth) / 2 + leftwidth;
|
||||
keyx = (vid.xres - fwidth) / 2 + leftwidth - dfsize/2;
|
||||
valuex = (vid.xres - fwidth) / 2 + leftwidth + innerwidth + dfsize/2;
|
||||
}
|
||||
|
||||
void display() {
|
||||
int N = items.size();
|
||||
dfsize = vid.fsize;
|
||||
#ifdef MOBILE
|
||||
dfsize *= 3;
|
||||
#endif
|
||||
#ifdef PANDORA
|
||||
dfsize *= 3;
|
||||
#endif
|
||||
dfspace = dfsize * 5/4;
|
||||
measure();
|
||||
while(tothei > vid.yres - 5 * vid.fsize) {
|
||||
int adfsize = int(dfsize * sqrt((vid.yres - 5. * vid.fsize) / tothei));
|
||||
if(adfsize < dfsize-1) dfsize = adfsize + 1;
|
||||
else dfsize--;
|
||||
dfspace = dfsize * 5/4;
|
||||
measure();
|
||||
}
|
||||
while(dialogwidth > vid.xres) {
|
||||
int adfsize = int(dfsize * sqrt(vid.xres * 1. / dialogwidth));
|
||||
if(adfsize < dfsize-1) dfsize = adfsize + 1;
|
||||
else dfsize--; // keep dfspace
|
||||
measure();
|
||||
}
|
||||
|
||||
tothei = (vid.yres - tothei) / 2;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
item& I = items[i];
|
||||
|
||||
if(I.type == diHelp) {
|
||||
tothei = displayLong(items[i].body, dfsize * items[i].scale / 100, tothei, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
int top = tothei;
|
||||
tothei += dfspace * I.scale / 100;
|
||||
int mid = (top + tothei) / 2;
|
||||
if(I.type == diTitle || I.type == diInfo) {
|
||||
displayfr(vid.xres/2, mid, 2, dfsize * I.scale/100, I.body, I.color, 8);
|
||||
}
|
||||
else if(I.type == diItem) {
|
||||
bool xthis = (mousey >= top && mousey < tothei);
|
||||
#ifdef MOBILE
|
||||
if(xthis && mousepressed)
|
||||
I.color = I.colorc;
|
||||
#else
|
||||
if(xthis && mousemoved) {
|
||||
highlight_text = I.body;
|
||||
mousemoved = false;
|
||||
}
|
||||
if(highlight_text == I.body) {
|
||||
I.color = (xthis&&mousepressed&&actonrelease) ? I.colorc : I.colors;
|
||||
}
|
||||
#endif
|
||||
if(!mousing)
|
||||
displayfr(keyx, mid, 2, dfsize * I.scale/100, I.keycaption, I.colork, 16);
|
||||
displayfr(itemx, mid, 2, dfsize * I.scale/100, I.body, I.color, 0);
|
||||
displayfr(valuex, mid, 2, dfsize * I.scale/100, I.value, I.colorv, 0);
|
||||
if(xthis) getcstat = I.key;
|
||||
}
|
||||
else if(I.type == diSlider) {
|
||||
bool xthis = (mousey >= top && mousey < tothei);
|
||||
displayfr(vid.xres*1/4, mid, 2, dfsize * I.scale/100, "(", I.color, 16);
|
||||
displayfr(vid.xres*1/4 + double(vid.xres/2 * I.param), mid, 2, dfsize * I.scale/100, "#", I.color, 8);
|
||||
displayfr(vid.xres*3/4, mid, 2, dfsize * I.scale/100, ")", I.color, 0);
|
||||
if(xthis) getcstat = I.key, inslider = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleNavigation(int &sym, int &uni) {
|
||||
#ifndef MOBILE
|
||||
if(uni == '\n' || uni == '\r' || sym == SDLK_KP5)
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem)
|
||||
if(items[i].body == highlight_text) {
|
||||
uni = sym = items[i].key;
|
||||
return;
|
||||
}
|
||||
if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) {
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem)
|
||||
highlight_text = items[i].body;
|
||||
}
|
||||
if(sym == SDLK_PAGEUP || sym == SDLK_KP9) {
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem) {
|
||||
highlight_text = items[i].body;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(sym == SDLK_UP || sym == SDLK_KP8) {
|
||||
string last = "";
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem)
|
||||
last = items[i].body;
|
||||
uni = sym = 0;
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem) {
|
||||
if(items[i].body == highlight_text) {
|
||||
highlight_text = last; return;
|
||||
}
|
||||
else last = items[i].body;
|
||||
}
|
||||
highlight_text = last;
|
||||
}
|
||||
if(sym == SDLK_DOWN || sym == SDLK_KP2) {
|
||||
int state = 0;
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem) {
|
||||
if(state) { highlight_text = items[i].body; return; }
|
||||
else if(items[i].body == highlight_text) state = 1;
|
||||
}
|
||||
for(int i=0; i<size(items); i++)
|
||||
if(items[i].type == diItem)
|
||||
highlight_text = items[i].body;
|
||||
uni = sym = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int colorhistory[10] = {
|
||||
0x202020FF, 0x800000FF, 0x008000FF, 0x000080FF,
|
||||
0x404040FF, 0xC0C0C0FF, 0x804000FF, 0xC0C000FF,
|
||||
0x408040FF, 0xFFD500FF
|
||||
}, lch;
|
||||
|
||||
unsigned int *palette;
|
||||
|
||||
void drawColorDialog(int color) {
|
||||
int ash = 8;
|
||||
|
||||
for(int j=0; j<10; j++) {
|
||||
int x = vid.xres / 2 + vid.fsize * 2 * (j-5);
|
||||
int y = vid.yres / 2- 5 * vid.fsize;
|
||||
|
||||
string s0 = ""; s0 += ('0'+j);
|
||||
|
||||
vid.fsize *= 2;
|
||||
displayColorButton(x, y, s0, '0'+j, 0, 0, colorhistory[j] >> ash);
|
||||
vid.fsize /= 2;
|
||||
}
|
||||
|
||||
if(palette) {
|
||||
int q = palette[0];
|
||||
for(int i=0; i<q; i++) {
|
||||
int x = vid.xres / 2 + vid.fsize * (2 * i-q);
|
||||
int y = vid.yres / 2- 7 * vid.fsize;
|
||||
string s0 = ""; s0 += ('a'+i);
|
||||
vid.fsize *= 2;
|
||||
displayColorButton(x, y, s0, 'a'+i, 0, 0, palette[i+1] >> ash);
|
||||
vid.fsize /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<4; i++) {
|
||||
int y = vid.yres / 2 + (2-i) * vid.fsize * 2;
|
||||
|
||||
displayColorButton(vid.xres / 4, y, "(", 0, 16, 0, 0xFFFFFF);
|
||||
string rgt = ") "; rgt += "ABGR" [i];
|
||||
displayColorButton(vid.xres * 3/4, y, rgt, 0, 0, 0, 0xFFFFFF);
|
||||
displayColorButton(vid.xres /4 + vid.xres * ((color >> (8*i)) & 0xFF) / 510, y, "#", 0, 8, 0, 0xFFFFFF);
|
||||
|
||||
if(mousey >= y - vid.fsize && mousey < y + vid.fsize)
|
||||
getcstat = 'A' + i, inslider = true;
|
||||
}
|
||||
|
||||
displayColorButton(vid.xres/2, vid.yres/2+vid.fsize * 6, XLAT("select this color") + " : " + itsh(color), ' ', 8, 0, color >> ash);
|
||||
}
|
||||
|
||||
// 0: nothing happened, 1: color accepted, 2: break
|
||||
int handleKeyColor(int sym, int uni, int& color) {
|
||||
|
||||
if(uni >= 'A' && uni <= 'D') {
|
||||
int x = (mousex - vid.xres/4) * 510 / vid.xres;
|
||||
if(x < 0) x = 0;
|
||||
if(x > 255) x = 255;
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[uni - 'A'] = x;
|
||||
}
|
||||
else if(uni == ' ') {
|
||||
bool inHistory = false;
|
||||
for(int i=0; i<10; i++) if(colorhistory[i] == (unsigned) color)
|
||||
inHistory = true;
|
||||
if(!inHistory) { colorhistory[lch] = color; lch++; lch %= 10; }
|
||||
return 1;
|
||||
}
|
||||
else if(uni >= '0' && uni <= '9') {
|
||||
color = colorhistory[uni - '0'];
|
||||
}
|
||||
else if(palette && uni >= 'a' && uni < 'a'+(int) palette[0]) {
|
||||
color = palette[1 + uni - 'a'];
|
||||
}
|
||||
else if(uni || sym == SDLK_F10) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int *colorPointer;
|
||||
emtype lastmode;
|
||||
|
||||
void openColorDialog(int& col, unsigned int *pal) {
|
||||
colorPointer = &col; palette = pal;
|
||||
lastmode = cmode; cmode = emColor;
|
||||
}
|
||||
|
||||
void handleColor(int sym, int uni) {
|
||||
int ret = handleKeyColor(sym, uni, *colorPointer);
|
||||
if(ret) cmode = lastmode;
|
||||
}
|
||||
|
||||
struct numberEditor {
|
||||
ld *editwhat;
|
||||
string s;
|
||||
ld vmin, vmax, step, dft;
|
||||
string title, help;
|
||||
ld (*scale) (ld);
|
||||
ld (*inverse_scale) (ld);
|
||||
int *intval; ld intbuf;
|
||||
bool positive;
|
||||
} ne;
|
||||
|
||||
bool editingDetail() {
|
||||
return ne.editwhat == &geom3::highdetail || ne.editwhat == &geom3::middetail;
|
||||
}
|
||||
|
||||
ld identity(ld x) { return x; }
|
||||
|
||||
void scaleSinh() {
|
||||
ne.scale = ASINH;
|
||||
ne.inverse_scale = sinh;
|
||||
}
|
||||
|
||||
void scaleLog() {
|
||||
ne.scale = log;
|
||||
ne.inverse_scale = exp;
|
||||
ne.positive = true;
|
||||
}
|
||||
|
||||
void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) {
|
||||
ne.editwhat = &x;
|
||||
ne.s = fts(x);
|
||||
ne.vmin = vmin;
|
||||
ne.vmax = vmax;
|
||||
ne.step = step;
|
||||
ne.dft = dft;
|
||||
ne.title = title;
|
||||
ne.help = help;
|
||||
lastmode = cmode; cmode = emNumber;
|
||||
ne.scale = ne.inverse_scale = identity;
|
||||
ne.intval = NULL;
|
||||
ne.positive = false;
|
||||
}
|
||||
|
||||
void editNumber(int& x, int vmin, int vmax, int step, int dft, string title, string help) {
|
||||
editNumber(ne.intbuf, vmin, vmax, step, dft, title, help);
|
||||
ne.intbuf = x; ne.intval = &x; ne.s = its(x);
|
||||
}
|
||||
|
||||
string disp(ld x) { if(ne.intval) return its((int) (x+.5)); else return fts(x); }
|
||||
|
||||
void affect(char kind) {
|
||||
|
||||
if(ne.intval) {
|
||||
if(kind == 's') sscanf(ne.s.c_str(), "%d", ne.intval), *ne.editwhat = *ne.intval;
|
||||
if(kind == 'v') *ne.intval = (int) (*ne.editwhat + .5), ne.s = its(*ne.intval);
|
||||
}
|
||||
else {
|
||||
if(kind == 's') {
|
||||
ld x;
|
||||
sscanf(ne.s.c_str(), LDF, &x);
|
||||
if(ne.positive && x <= 0) return;
|
||||
*ne.editwhat = x;
|
||||
}
|
||||
if(kind == 'v') ne.s = fts(*ne.editwhat);
|
||||
}
|
||||
|
||||
#ifndef NOAUDIO
|
||||
if(ne.intval == &musicvolume) {
|
||||
if(musicvolume < 0)
|
||||
*ne.editwhat = musicvolume = 0, affect('v');
|
||||
else if(musicvolume > MIX_MAX_VOLUME)
|
||||
*ne.editwhat = musicvolume = MIX_MAX_VOLUME, affect('v');
|
||||
#ifdef SDLAUDIO
|
||||
else Mix_VolumeMusic(musicvolume);
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
settingsChanged = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(ne.intval == &effvolume) {
|
||||
if(effvolume < 0)
|
||||
*ne.editwhat = effvolume = 0, affect('v');
|
||||
else if(effvolume > MIX_MAX_VOLUME)
|
||||
*ne.editwhat = effvolume = MIX_MAX_VOLUME, affect('v');
|
||||
#ifdef ANDROID
|
||||
settingsChanged = true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ne.intval == &vid.framelimit && vid.framelimit < 5)
|
||||
*ne.editwhat = vid.framelimit = 5, affect('v');
|
||||
|
||||
#ifdef MOBILE
|
||||
if(ne.intval == &fontscale && fontscale < 50)
|
||||
*ne.editwhat = fontscale = 50, affect('v');
|
||||
#endif
|
||||
|
||||
if(ne.intval == &sightrange && sightrange < 4)
|
||||
*ne.editwhat = sightrange = 4, affect('v');
|
||||
|
||||
int msr = cheater ? 15 : 7;
|
||||
|
||||
if(ne.intval == &sightrange && sightrange > msr)
|
||||
*ne.editwhat = sightrange = msr, affect('v');
|
||||
|
||||
if(ne.intval == &conformal::bandhalf && conformal::bandhalf < 5)
|
||||
*ne.editwhat = *ne.intval = 5, affect('v');
|
||||
|
||||
if(ne.intval == &conformal::bandsegment && conformal::bandsegment < 500)
|
||||
*ne.editwhat = *ne.intval = 500, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::coefid && polygonal::coefid < 0)
|
||||
*ne.editwhat = *ne.intval = 0, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::coefid && polygonal::coefid >= MSI)
|
||||
*ne.editwhat = *ne.intval = MSI-1, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::deg && polygonal::deg < 0)
|
||||
*ne.editwhat = *ne.intval = MSI-1, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::deg && polygonal::deg >= MSI)
|
||||
*ne.editwhat = *ne.intval = MSI-1, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::SI) polygonal::solve();
|
||||
if(ne.editwhat == &polygonal::STAR) polygonal::solve();
|
||||
|
||||
conformal::applyIB();
|
||||
|
||||
if(ne.editwhat == &geom3::highdetail && geom3::highdetail > geom3::middetail)
|
||||
geom3::middetail = geom3::highdetail;
|
||||
|
||||
if(ne.editwhat == &geom3::middetail && geom3::highdetail > geom3::middetail)
|
||||
geom3::highdetail = geom3::middetail;
|
||||
|
||||
if(lastmode == em3D) buildpolys(), resetGL();
|
||||
}
|
||||
|
||||
void drawNumberDialog() {
|
||||
init(ne.title);
|
||||
addInfo(ne.s);
|
||||
addSlider(ne.scale(ne.vmin), ne.scale(*ne.editwhat), ne.scale(ne.vmax), 500);
|
||||
addBreak(100);
|
||||
#ifndef MOBILE
|
||||
addHelp("You can scroll with arrow keys -- Ctrl to fine-tune");
|
||||
addBreak(100);
|
||||
#endif
|
||||
|
||||
addItem("return", ' ');
|
||||
addSelItem("default value", disp(ne.dft), SDLK_HOME);
|
||||
|
||||
addBreak(100);
|
||||
|
||||
if(lastmode == em3D) ne.help = explain3D(ne.editwhat);
|
||||
|
||||
if(ne.help != "") {
|
||||
addHelp(ne.help);
|
||||
bool scal = size(ne.help) > 160;
|
||||
#ifndef MOBILE
|
||||
#ifndef PANDORA
|
||||
scal = false;
|
||||
#endif
|
||||
#endif
|
||||
if(scal) lastItem().scale = 30;
|
||||
}
|
||||
|
||||
if(ne.editwhat == &vid.alpha) {
|
||||
addBreak(100);
|
||||
addSelItem(sphere ? "stereographic" : "Poincaré model", "1", 'p');
|
||||
addSelItem(sphere ? "gnomonic" : "Klein model", "0", 'k');
|
||||
addItem(sphere ? "towards orthographic" : "towards Gans model", 'o');
|
||||
}
|
||||
|
||||
if(ne.editwhat == &ne.intbuf && ne.intval == &sightrange && cheater)
|
||||
addBoolItem("overgenerate", overgenerate, 'o');
|
||||
|
||||
display();
|
||||
}
|
||||
|
||||
void handleNumber(int sym, int uni) {
|
||||
handleNavigation(sym, uni);
|
||||
if((uni >= '0' && uni <= '9') || (uni == '.' && !ne.intval) || (uni == '-' && !ne.positive)) {
|
||||
ne.s += uni;
|
||||
affect('s');
|
||||
}
|
||||
else if(uni == '\b' || uni == '\t') {
|
||||
ne.s = ne.s. substr(0, size(ne.s)-1);
|
||||
sscanf(ne.s.c_str(), LDF, ne.editwhat);
|
||||
affect('s');
|
||||
}
|
||||
#ifndef MOBILE
|
||||
else if(sym == SDLK_RIGHT || sym == SDLK_KP6) {
|
||||
if(ne.intval && abs(shiftmul) < .6)
|
||||
(*ne.editwhat)++;
|
||||
else
|
||||
*ne.editwhat = ne.inverse_scale(ne.scale(*ne.editwhat) + shiftmul * ne.step);
|
||||
affect('v');
|
||||
}
|
||||
else if(sym == SDLK_LEFT || sym == SDLK_KP4) {
|
||||
if(ne.intval && abs(shiftmul) < .6)
|
||||
(*ne.editwhat)--;
|
||||
else
|
||||
*ne.editwhat = ne.inverse_scale(ne.scale(*ne.editwhat) - shiftmul * ne.step);
|
||||
affect('v');
|
||||
}
|
||||
#endif
|
||||
else if(sym == SDLK_HOME) {
|
||||
*ne.editwhat = ne.dft;
|
||||
affect('v');
|
||||
}
|
||||
else if(uni == 500) {
|
||||
ld d = (mousex - vid.xres/4 + .0) / (vid.xres/2);
|
||||
*ne.editwhat =
|
||||
ne.inverse_scale(d * (ne.scale(ne.vmax) - ne.scale(ne.vmin)) + ne.scale(ne.vmin));
|
||||
affect('v');
|
||||
}
|
||||
else if(uni == 'o' && ne.editwhat == &ne.intbuf && ne.intval == &sightrange && cheater)
|
||||
overgenerate = !overgenerate;
|
||||
else if(uni == 'p' && ne.editwhat == &vid.alpha) {
|
||||
*ne.editwhat = 1; vid.scale = 1; ne.s = "1";
|
||||
}
|
||||
else if(uni == 'k' && ne.editwhat == &vid.alpha) {
|
||||
*ne.editwhat = 0; vid.scale = 1; ne.s = "0";
|
||||
}
|
||||
else if((uni == 'i' || uni == 'I' || uni == 'o' || uni == 'O') && ne.editwhat == &vid.alpha) {
|
||||
double d = exp(shiftmul/10);
|
||||
vid.alpha *= d;
|
||||
vid.scale *= d;
|
||||
ne.s = fts(vid.alpha);
|
||||
}
|
||||
else if(uni) {
|
||||
cmode = lastmode;
|
||||
}
|
||||
}
|
||||
|
||||
int nlpage = 1;
|
||||
int wheelshift = 0;
|
||||
|
||||
int handlePage(int& nl, int& nlm, int perpage) {
|
||||
nlm = nl;
|
||||
int onl = nl;
|
||||
int ret = 0;
|
||||
if(nlpage) {
|
||||
nl = nlm = perpage;
|
||||
if(nlpage == 2) ret = nlm;
|
||||
int w = wheelshift;
|
||||
int realw = 0;
|
||||
while(w<0 && ret) {
|
||||
ret--; w++; realw--;
|
||||
}
|
||||
while(w>0 && ret+perpage < onl) {
|
||||
ret++; w--; realw++;
|
||||
}
|
||||
wheelshift = realw;
|
||||
if(ret+nl > onl) nl = onl-ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void displayPageButtons(int i, bool pages) {
|
||||
int i0 = vid.yres - vid.fsize;
|
||||
int xr = vid.xres / 80;
|
||||
if(pages) if(displayfrZ(xr*8, i0, 1, vid.fsize, IFM("1 - ") + XLAT("page") + " 1", nlpage == 1 ? 0xD8D8C0 : 0xC0C0C0, 8))
|
||||
getcstat = '1';
|
||||
if(pages) if(displayfrZ(xr*24, i0, 1, vid.fsize, IFM("2 - ") + XLAT("page") + " 2", nlpage == 1 ? 0xD8D8C0 : 0xC0C0C0, 8))
|
||||
getcstat = '2';
|
||||
if(pages) if(displayfrZ(xr*40, i0, 1, vid.fsize, IFM("3 - ") + XLAT("all"), nlpage == 1 ? 0xD8D8C0 : 0xC0C0C0, 8))
|
||||
getcstat = '3';
|
||||
if(i&1) if(displayfrZ(xr*56, i0, 1, vid.fsize, IFM("0 - ") + XLAT("return"), 0xC0C0C0, 8))
|
||||
getcstat = '0';
|
||||
if(i&2) if(displayfrZ(xr*72, i0, 1, vid.fsize, IFM("F1 - ") + XLAT("help"), 0xC0C0C0, 8))
|
||||
getcstat = SDLK_F1;
|
||||
}
|
||||
|
||||
bool handlePageButtons(int uni) {
|
||||
if(uni == '1') nlpage = 1, wheelshift = 0;
|
||||
else if(uni == '2') nlpage = 2, wheelshift = 0;
|
||||
else if(uni == '3') nlpage = 0, wheelshift = 0;
|
||||
else if(uni == PSEUDOKEY_WHEELUP) wheelshift--;
|
||||
else if(uni == PSEUDOKEY_WHEELDOWN) wheelshift++;
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,234 @@
|
|||
#define ISANDROID 0
|
||||
#define ISMOBILE 1
|
||||
#define ISIOS 0
|
||||
#define MOBILE
|
||||
#define MOBPAR_FORMAL int
|
||||
#define MOBPAR_ACTUAL 0
|
||||
#define FAKEMOBILE
|
||||
#define MIX_MAX_VOLUME 128
|
||||
|
||||
const char *scorefile = "fakemobile_score.txt";
|
||||
const char *conffile = "fakemobile_config.txt";
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include "init.cpp"
|
||||
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include <SDL/SDL_gfxPrimitives.h>
|
||||
|
||||
#undef main
|
||||
|
||||
void playSound(cell *, const string &s, int vol) {
|
||||
printf("play sound: %s vol %d\n", s.c_str(), vol);
|
||||
}
|
||||
|
||||
SDL_Surface *s;
|
||||
|
||||
int gdpos = 0;
|
||||
|
||||
int gdpop() { return graphdata[gdpos++]; }
|
||||
|
||||
TTF_Font *font[256];
|
||||
|
||||
bool rawdisplaystr(int x, int y, int shift, int size, const char *str, int color, int align) {
|
||||
|
||||
if(strlen(str) == 0) return false;
|
||||
|
||||
if(size <= 0 || size > 255) {
|
||||
return false;
|
||||
}
|
||||
SDL_Color col;
|
||||
col.r = (color >> 16) & 255;
|
||||
col.g = (color >> 8 ) & 255;
|
||||
col.b = (color >> 0 ) & 255;
|
||||
|
||||
col.r >>= darken; col.g >>= darken; col.b >>= darken;
|
||||
|
||||
if(!font[size])
|
||||
font[size] = TTF_OpenFont("VeraBd.ttf", size);
|
||||
|
||||
SDL_Surface *txt = TTF_RenderText_Solid(font[size], str, col);
|
||||
|
||||
if(txt == NULL) return false;
|
||||
|
||||
SDL_Rect rect;
|
||||
|
||||
rect.w = txt->w;
|
||||
rect.h = txt->h;
|
||||
|
||||
rect.x = x - rect.w * align / 16;
|
||||
rect.y = y - rect.h/2;
|
||||
|
||||
bool clicked = (mousex >= rect.x && mousey >= rect.y && mousex <= rect.x+rect.w && mousey <= rect.y+rect.h);
|
||||
|
||||
SDL_BlitSurface(txt, NULL, s,&rect);
|
||||
SDL_FreeSurface(txt);
|
||||
|
||||
return clicked;
|
||||
}
|
||||
|
||||
int textwidth(int siz, const string &str) {
|
||||
if(size(str) == 0) return 0;
|
||||
|
||||
if(!font[siz]) font[siz] = TTF_OpenFont("VeraBd.ttf", siz);
|
||||
|
||||
int w, h;
|
||||
TTF_SizeUTF8(font[siz], str.c_str(), &w, &h);
|
||||
// printf("width = %d [%d]\n", w, size(str));
|
||||
return w;
|
||||
}
|
||||
|
||||
char action;
|
||||
|
||||
int getticks() { return SDL_GetTicks(); }
|
||||
|
||||
bool currentlyConnecting() { return false; }
|
||||
bool currentlyConnected() { return false; }
|
||||
void viewAchievements() { printf("view Achievements\n"); }
|
||||
void viewLeaderboard(string id) { printf("view Leaderboard :: %s\n", id.c_str()); }
|
||||
void switchGoogleConnection() { printf("sgc\n"); }
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
initAll();
|
||||
|
||||
vid.xres = 800; vid.yres = 450;
|
||||
vid.usingGL = false;
|
||||
// 450; vid.yres = 600;
|
||||
|
||||
s= SDL_SetVideoMode(vid.xres, vid.yres, 32, 0);
|
||||
|
||||
if(TTF_Init() != 0) {
|
||||
printf("Failed to initialize TTF.\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int mx = 0; int my = 0; bool _clicked = false;
|
||||
int action = 0;
|
||||
|
||||
firstland = laMinefield;
|
||||
|
||||
items[itGreenStone] = 100;
|
||||
items[itDiamond] = 50;
|
||||
for(int i=1; i<10; i++) kills[i] = 5;
|
||||
|
||||
while(true) {
|
||||
|
||||
SDL_LockSurface(s);
|
||||
memset(s->pixels, 0, vid.xres * vid.yres * 4);
|
||||
SDL_UnlockSurface(s);
|
||||
|
||||
mousex = mx;
|
||||
mousey = my;
|
||||
clicked = _clicked;
|
||||
|
||||
mobile_draw(MOBPAR_ACTUAL);
|
||||
action = 0;
|
||||
|
||||
gdpos = 0;
|
||||
while(gdpos < graphdata.size()) {
|
||||
switch(gdpop()) {
|
||||
case 2: {
|
||||
int x = gdpop(), y = gdpop(), al = gdpop();
|
||||
int color = gdpop();
|
||||
int size = gdpop();
|
||||
int b = gdpop();
|
||||
int n = gdpop();
|
||||
string s;
|
||||
for(int i=0; i<n; i++) s += char(gdpop());
|
||||
rawdisplaystr(x, y, 0, size, s.c_str(), color, al);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
int col = gdpop();
|
||||
int otl = gdpop();
|
||||
int num = gdpop();
|
||||
|
||||
Sint16 xpox[6000], xpoy[6000];
|
||||
|
||||
// printf("%4d polygon %d\n", gdpos, num);
|
||||
for(int i=0; i<num; i++) xpox[i] = gdpop(), xpoy[i] = gdpop();
|
||||
|
||||
filledPolygonColor(s, xpox, xpoy, num, col);
|
||||
aapolygonColor(s, xpox, xpoy, num, otl);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
int col = gdpop();
|
||||
int num = gdpop();
|
||||
|
||||
for(int i=0; i<num; i++) polyx[i] = gdpop(), polyy[i] = gdpop();
|
||||
|
||||
for(int i=0; i<num-1; i++)
|
||||
aalineColor(s, polyx[i], polyy[i], polyx[i+1], polyy[i+1], col);
|
||||
}
|
||||
|
||||
case 4: {
|
||||
int col = gdpop();
|
||||
int x = gdpop(), y = gdpop(), rad = gdpop();
|
||||
|
||||
aacircleColor(s, x, y, rad, (col << 8) + 0xFF);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
SDL_UpdateRect(s, 0, 0, vid.xres, vid.yres);
|
||||
|
||||
SDL_Event ev;
|
||||
while(SDL_PollEvent(&ev)) {
|
||||
|
||||
if(ev.type == SDL_MOUSEBUTTONDOWN) {
|
||||
mx = ev.button.x;
|
||||
my = ev.button.y;
|
||||
_clicked = true;
|
||||
}
|
||||
|
||||
if(ev.type == SDL_MOUSEBUTTONUP) {
|
||||
_clicked = false;
|
||||
}
|
||||
|
||||
if(ev.type == SDL_MOUSEMOTION) {
|
||||
mx = ev.motion.x;
|
||||
my = ev.motion.y;
|
||||
}
|
||||
|
||||
if(ev.type == SDL_KEYDOWN) {
|
||||
int sym = ev.key.keysym.sym;
|
||||
/* if(sym == '1') {
|
||||
printf("Number of cells explored, by distance from the player:\n");
|
||||
for(int i=0; i<10; i++) printf(" %d", explore[i]); printf("\n");
|
||||
return 0;
|
||||
}
|
||||
else if(sym == '2') {
|
||||
items[rand() % ittypes] += 3;
|
||||
kills[rand() % motypes] += 3;
|
||||
}
|
||||
else if(sym == '3') {
|
||||
items[itHell] = 0;
|
||||
items[itGreenStone] = 100;
|
||||
}
|
||||
action = sym; */
|
||||
extra ex;
|
||||
mousing = false;
|
||||
handlekey(sym, sym, ex);
|
||||
}
|
||||
|
||||
if(ev.type == SDL_QUIT) {
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
clearMemory();
|
||||
}
|
||||
|
||||
void openURL() {
|
||||
printf("< openURL > \n");
|
||||
}
|
|
@ -0,0 +1,684 @@
|
|||
|
||||
namespace fieldpattern {
|
||||
|
||||
extern int subpathid;
|
||||
extern int subpathorder;
|
||||
|
||||
bool isprime(int n) {
|
||||
for(int k=2; k<n; k++) if(n%k == 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct matrix {
|
||||
int a[3][3];
|
||||
int* operator [] (int k) { return a[k]; }
|
||||
const int* operator [] (int k) const { return a[k]; }
|
||||
};
|
||||
|
||||
bool operator == (const matrix& A, const matrix& B) {
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++)
|
||||
if(A[i][j] != B[i][j]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator != (const matrix& A, const matrix& B) {
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++)
|
||||
if(A[i][j] != B[i][j]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator < (const matrix& A, const matrix& B) {
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++)
|
||||
if(A[i][j] != B[i][j]) return A[i][j] < B[i][j];
|
||||
return false;
|
||||
}
|
||||
|
||||
int btspin(int id, int d) {
|
||||
return 7*(id/7) + (id + d) % 7;
|
||||
}
|
||||
|
||||
struct fpattern {
|
||||
|
||||
int Prime, wsquare, Field;
|
||||
// we perform our computations in the field Z_Prime[w] where w^2 equals wsquare
|
||||
// (or simply Z_Prime for wsquare == 0)
|
||||
|
||||
#define EASY
|
||||
// 'easy' assumes that all elements of the field actually used
|
||||
// are of form n or mw (not n+mw), and cs and ch are both of form n
|
||||
// by experimentation, such cs and ch always exist
|
||||
// many computations are much simpler under that assumption
|
||||
|
||||
#ifndef EASY
|
||||
static int neasy;
|
||||
|
||||
int m(int x) { x %= Prime; if(x<0) x+= Prime; return x; }
|
||||
#endif
|
||||
|
||||
int sub(int a, int b) {
|
||||
#ifdef EASY
|
||||
return (a + b * (Prime-1)) % Prime;
|
||||
#else
|
||||
return m(a%Prime-b%Prime) + Prime * m(a/Prime-b/Prime);
|
||||
#endif
|
||||
}
|
||||
|
||||
int add(int a, int b) {
|
||||
#ifdef EASY
|
||||
return (a+b)%Prime;
|
||||
#else
|
||||
return m(a%Prime+b%Prime) + Prime * m(a/Prime+b/Prime);
|
||||
#endif
|
||||
}
|
||||
|
||||
int mul(int tx, int ty) {
|
||||
#ifdef EASY
|
||||
return (tx*ty*((tx<0&&ty<0)?wsquare:1)) % Prime;
|
||||
#else
|
||||
if(tx >= Prime && tx % Prime) neasy++;
|
||||
if(ty >= Prime && ty % Prime) neasy++;
|
||||
int x[2], y[2], z[3];
|
||||
for(int i=0; i<3; i++) z[i] = 0;
|
||||
for(int i=0; i<2; i++)
|
||||
x[i] = tx%Prime, tx /= Prime;
|
||||
for(int i=0; i<2; i++)
|
||||
y[i] = ty%Prime, ty /= Prime;
|
||||
for(int i=0; i<2; i++)
|
||||
for(int j=0; j<2; j++)
|
||||
z[i+j] = (z[i+j] + x[i] * y[j]) % Prime;
|
||||
z[0] += z[2] * wsquare;
|
||||
|
||||
return m(z[0]) + Prime * m(z[1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
int sqr(int x) { return mul(x,x); }
|
||||
|
||||
matrix mmul(const matrix& A, const matrix& B) {
|
||||
matrix res;
|
||||
for(int i=0; i<3; i++) for(int k=0; k<3; k++) {
|
||||
#ifdef EASY
|
||||
res[i][k] =
|
||||
(mul(A[i][0], B[0][k]) + mul(A[i][1], B[1][k]) + mul(A[i][2], B[2][k])) % Prime;
|
||||
#else
|
||||
int t=0;
|
||||
for(int j=0; j<3; j++) t = add(t, mul(A[i][j], B[j][k]));
|
||||
res[i][k] = t;
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
map<matrix, int> matcode;
|
||||
vector<matrix> matrices;
|
||||
|
||||
vector<string> qpaths;
|
||||
|
||||
vector<matrix> qcoords;
|
||||
|
||||
matrix Id, R, P;
|
||||
|
||||
matrix strtomatrix(string s) {
|
||||
matrix res = Id;
|
||||
matrix m = Id;
|
||||
for(int i=size(s)-1; i>=0; i--)
|
||||
if(s[i] == 'R') res = mmul(R, res);
|
||||
else if (s[i] == 'P') res = mmul(P, res);
|
||||
else if (s[i] == 'x') { m[0][0] = -1; res = mmul(m, res); m[0][0] = +1; }
|
||||
else if (s[i] == 'y') { m[1][1] = -1; res = mmul(m, res); m[1][1] = +1; }
|
||||
else if (s[i] == 'z') { m[2][2] = -1; res = mmul(m, res); m[2][2] = +1; }
|
||||
return res;
|
||||
}
|
||||
|
||||
void addas(const matrix& M, int i) {
|
||||
if(!matcode.count(M)) {
|
||||
matcode[M] = i;
|
||||
for(int j=0; j<size(qcoords); j++)
|
||||
addas(mmul(M, qcoords[j]), i);
|
||||
}
|
||||
}
|
||||
|
||||
void add(const matrix& M) {
|
||||
if(!matcode.count(M)) {
|
||||
int i = matrices.size();
|
||||
matcode[M] = i, matrices.push_back(M);
|
||||
for(int j=0; j<size(qcoords); j++)
|
||||
addas(mmul(M, qcoords[j]), i);
|
||||
add(mmul(R, M));
|
||||
}
|
||||
}
|
||||
|
||||
#define MXF 1000000
|
||||
|
||||
vector<int> connections;
|
||||
|
||||
vector<int> inverses;
|
||||
vector<int> rrf; // rrf[i] equals gmul(i, 6)
|
||||
vector<int> rpf; // rpf[i] equals gmul(i, 7)
|
||||
|
||||
matrix mpow(matrix M, int N) {
|
||||
while((N&1) == 0) N >>= 1, M = mmul(M, M);
|
||||
matrix res = M;
|
||||
N >>= 1;
|
||||
while(N) {
|
||||
M = mmul(M,M); if(N&1) res = mmul(res, M);
|
||||
N >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int gmul(int a, int b) { return matcode[mmul(matrices[a], matrices[b])]; }
|
||||
int gpow(int a, int N) { return matcode[mpow(matrices[a], N)]; }
|
||||
|
||||
pair<int,bool> gmul(pair<int, bool> a, int b) {
|
||||
return make_pair(gmul(a.first,b), a.second);
|
||||
}
|
||||
|
||||
int order(const matrix& M) {
|
||||
int cnt = 1;
|
||||
matrix Po = M;
|
||||
while(Po != Id) Po = mmul(Po, M), cnt++;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
string decodepath(int i) {
|
||||
string s;
|
||||
while(i) {
|
||||
if(i % 7) i--, s += 'R';
|
||||
else i = connections[i], s += 'P';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int orderstats();
|
||||
|
||||
int cs, sn, ch, sh;
|
||||
|
||||
int solve() {
|
||||
|
||||
for(int a=0; a<3; a++) for(int b=0; b<3; b++) Id[a][b] = a==b?1:0;
|
||||
|
||||
if(!isprime(Prime)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(int pw=1; pw<3; pw++) {
|
||||
if(pw>3) break;
|
||||
Field = pw==1? Prime : Prime*Prime;
|
||||
|
||||
if(pw == 2) {
|
||||
for(wsquare=1; wsquare<Prime; wsquare++) {
|
||||
int roots = 0;
|
||||
for(int a=0; a<Prime; a++) if((a*a)%Prime == wsquare) roots++;
|
||||
if(!roots) break;
|
||||
}
|
||||
} else wsquare = 0;
|
||||
|
||||
#ifdef EASY
|
||||
int sqrts[Prime];
|
||||
for(int k=0; k<Prime; k++) sqrts[k] = 0;
|
||||
for(int k=1-Prime; k<Prime; k++) sqrts[sqr(k)] = k;
|
||||
int fmax = Prime;
|
||||
#else
|
||||
int sqrts[Field];
|
||||
for(int k=0; k<Field; k++) sqrts[sqr(k)] = k;
|
||||
int fmax = Field;
|
||||
#endif
|
||||
|
||||
if(Prime == 13 && wsquare) {
|
||||
for(int i=0; i<Prime; i++) printf("%3d", sqrts[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++)
|
||||
R[i][j] = P[i][j] = i==j ? 1 : 0;
|
||||
|
||||
for(cs=0; cs<fmax; cs++) {
|
||||
int sb = sub(1, sqr(cs));
|
||||
|
||||
sn = sqrts[sb];
|
||||
|
||||
R[0][0] = cs; R[1][1] = cs;
|
||||
R[0][1] = sn; R[1][0] = sub(0, sn);
|
||||
|
||||
matrix Z = R;
|
||||
for(int i=0; i<6; i++) Z = mmul(Z, R);
|
||||
|
||||
if(Z != Id) continue;
|
||||
if(R[0][0] == 1) continue;
|
||||
|
||||
for(ch=2; ch<fmax; ch++) {
|
||||
int chx = sub(mul(ch,ch), 1);
|
||||
|
||||
sh = sqrts[chx];
|
||||
P[0][0] = sub(0, ch);
|
||||
P[0][2] = sub(0, sh);
|
||||
P[1][1] = Prime-1;
|
||||
P[2][0] = sh;
|
||||
P[2][2] = ch;
|
||||
|
||||
matrix Z = mmul(P, R);
|
||||
Z = mmul(Z, mmul(Z, Z));
|
||||
if(Z == Id) return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
void build() {
|
||||
|
||||
for(int i=0; i<size(qpaths); i++) {
|
||||
matrix M = strtomatrix(qpaths[i]);
|
||||
qcoords.push_back(M);
|
||||
printf("Solved %s as matrix of order %d\n", qpaths[i].c_str(), order(M));
|
||||
}
|
||||
|
||||
matcode.clear(); matrices.clear();
|
||||
add(Id);
|
||||
if(matrices.size() != 7) { printf("Error: rotation crash\n"); exit(1); }
|
||||
|
||||
connections.clear();
|
||||
|
||||
for(int i=0; i<(int)matrices.size(); i++) {
|
||||
|
||||
matrix M = matrices[i];
|
||||
|
||||
matrix PM = mmul(P, M);
|
||||
|
||||
add(PM);
|
||||
|
||||
if(matrices.size() % 7) { printf("Error: rotation crash\n"); exit(1); }
|
||||
|
||||
if(!matcode.count(PM)) { printf("Error: not marked\n"); exit(1); }
|
||||
|
||||
connections.push_back(matcode[PM]);
|
||||
}
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "Computing inverses...\n"));
|
||||
int N = size(matrices);
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "Number of heptagons: %d\n", N));
|
||||
|
||||
rrf.resize(N); rrf[0] = 6;
|
||||
for(int i=0; i<N; i++)
|
||||
rrf[btspin(i,1)] = btspin(rrf[i], 1),
|
||||
rrf[connections[i]] = connections[rrf[i]];
|
||||
|
||||
rpf.resize(N); rpf[0] = 7;
|
||||
for(int i=0; i<N; i++)
|
||||
rpf[btspin(i,1)] = btspin(rpf[i], 1),
|
||||
rpf[connections[i]] = connections[rpf[i]];
|
||||
|
||||
inverses.resize(N);
|
||||
inverses[0] = 0;
|
||||
for(int i=0; i<N; i++) // inverses[i] = gpow(i, N-1);
|
||||
inverses[btspin(i,1)] = rrf[inverses[i]], // btspin(inverses[i],6),
|
||||
inverses[connections[i]] = rpf[inverses[i]];
|
||||
|
||||
int errs = 0;
|
||||
for(int i=0; i<N; i++) if(gmul(i, inverses[i])) errs++;
|
||||
if(errs) printf("errs = %d\n", errs);
|
||||
|
||||
if(0) for(int i=0; i<size(matrices); i++) {
|
||||
printf("%5d/%4d", connections[i], inverses[i]);
|
||||
if(i%7 == 6) printf("\n");
|
||||
}
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "Built.\n"));
|
||||
}
|
||||
|
||||
vector<char> disthep;
|
||||
vector<char> disthex;
|
||||
|
||||
vector<char> distwall, distriver, distwall2, distriverleft, distriverright, distflower;
|
||||
|
||||
vector<eItem> markers;
|
||||
|
||||
int getdist(pair<int,bool> a, vector<char>& dists) {
|
||||
if(!a.second) return dists[a.first];
|
||||
int m = 60;
|
||||
int ma = dists[a.first];
|
||||
int mb = dists[connections[btspin(a.first, 3)]];
|
||||
int mc = dists[connections[btspin(a.first, 4)]];
|
||||
m = min(m, 1 + ma);
|
||||
m = min(m, 1 + mb);
|
||||
m = min(m, 1 + mc);
|
||||
if(m <= 2 && ma+mb+mc <= m*3-2) return m-1; // special case
|
||||
m = min(m, 2 + dists[connections[btspin(a.first, 2)]]);
|
||||
m = min(m, 2 + dists[connections[btspin(a.first, 5)]]);
|
||||
m = min(m, 2 + dists[connections[btspin(connections[btspin(a.first, 3)], 5)]]);
|
||||
return m;
|
||||
}
|
||||
|
||||
int getdist(pair<int,bool> a, pair<int,bool> b) {
|
||||
if(a.first == b.first) return a.second == b.second ? 0 : 1;
|
||||
if(b.first) a.first = gmul(a.first, inverses[b.first]), b.first = 0;
|
||||
return getdist(a, b.second ? disthex : disthep);
|
||||
}
|
||||
|
||||
int maxdist, otherpole, circrad, wallid, wallorder, riverid;
|
||||
|
||||
int dijkstra(vector<char>& dists, vector<int> indist[64]) {
|
||||
int N = connections.size();
|
||||
dists.resize(N);
|
||||
for(int i=0; i<N; i++) dists[i] = 60;
|
||||
int maxd = 0;
|
||||
for(int i=0; i<64; i++) while(!indist[i].empty()) {
|
||||
int at = indist[i].back();
|
||||
indist[i].pop_back();
|
||||
if(dists[at] <= i) continue;
|
||||
maxd = i;
|
||||
dists[at] = i;
|
||||
for(int q=0; q<7; q++) {
|
||||
dists[at] = i;
|
||||
if(purehepta)
|
||||
indist[i+1].push_back(connections[at]);
|
||||
else {
|
||||
indist[i+2].push_back(connections[at]);
|
||||
indist[i+3].push_back(connections[btspin(connections[at], 2)]);
|
||||
}
|
||||
at = btspin(at, 1);
|
||||
}
|
||||
}
|
||||
return maxd;
|
||||
}
|
||||
|
||||
void analyze() {
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "purehepta = %d\n", purehepta));
|
||||
int N = connections.size();
|
||||
|
||||
markers.resize(N);
|
||||
|
||||
vector<int> indist[64];
|
||||
|
||||
indist[0].push_back(0);
|
||||
int md0 = dijkstra(disthep, indist);
|
||||
|
||||
indist[1].push_back(0);
|
||||
indist[1].push_back(connections[3]);
|
||||
indist[1].push_back(connections[4]);
|
||||
indist[2].push_back(connections[btspin(connections[3], 5)]);
|
||||
indist[2].push_back(connections[2]);
|
||||
indist[2].push_back(connections[5]);
|
||||
int md1 = dijkstra(disthex, indist);
|
||||
|
||||
maxdist = max(md0, md1);
|
||||
|
||||
otherpole = 0;
|
||||
|
||||
for(int i=0; i<N; i+=7) {
|
||||
int mp = 0;
|
||||
for(int q=0; q<7; q++) if(disthep[connections[i+q]] < disthep[i]) mp++;
|
||||
if(mp == 7) {
|
||||
bool eq = true;
|
||||
for(int q=0; q<7; q++) if(disthep[connections[i+q]] != disthep[connections[i]]) eq = false;
|
||||
if(eq) {
|
||||
// for(int q=0; q<7; q++) printf("%3d", disthep[connections[i+q]]);
|
||||
// printf(" (%2d) at %d\n", disthep[i], i);
|
||||
if(disthep[i] > disthep[otherpole]) otherpole = i;
|
||||
// for(int r=0; r<7; r++) {
|
||||
// printf("Matrix: "); for(int a=0; a<3; a++) for(int b=0; b<3; b++)
|
||||
// printf("%4d", matrices[i+r][a][b]); printf("\n");
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
circrad = 99;
|
||||
|
||||
for(int i=0; i<N; i++) for(int u=2; u<4; u++) if(disthep[i] < circrad)
|
||||
if(disthep[connections[i]] < disthep[i] && disthep[connections[btspin(i,u)]] < disthep[i])
|
||||
circrad = disthep[i];
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "maxdist = %d otherpole = %d circrad = %d\n", maxdist, otherpole, circrad));
|
||||
|
||||
matrix PRRR = strtomatrix("PRRR");
|
||||
matrix PRRPRRRRR = strtomatrix("PRRPRRRRR");
|
||||
matrix PRRRP = strtomatrix("PRRRP");
|
||||
matrix PRP = strtomatrix("PRP");
|
||||
matrix PR = strtomatrix("PR");
|
||||
matrix Wall = strtomatrix("RRRPRRRRRPRRRP");
|
||||
|
||||
wallorder = order(Wall);
|
||||
wallid = matcode[Wall];
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "wall order = %d\n", wallorder));
|
||||
|
||||
#define SETDIST(X, d, it) {int c = matcode[X]; indist[d].push_back(c); if(!it) ; else if(markers[c] && markers[c] != it) markers[c] = itBuggy; else markers[c] = it; }
|
||||
|
||||
matrix W = Id;
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itAmethyst)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = P;
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itEmerald)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
|
||||
int walldist = dijkstra(distwall, indist);
|
||||
DEBB(DF_FIELD, (debugfile, "wall dist = %d\n", walldist));
|
||||
|
||||
|
||||
W = strtomatrix("RRRRPR");
|
||||
for(int j=0; j<wallorder; j++) {
|
||||
W = mmul(W, Wall);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itNone)
|
||||
SETDIST(mmul(PRRR, W), 1, itNone)
|
||||
W = mmul(Wall, W);
|
||||
}
|
||||
}
|
||||
dijkstra(distwall2, indist);
|
||||
|
||||
int rpushid = matcode[PRRPRRRRR];
|
||||
riverid = 0;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
int j = i;
|
||||
int ipush = gmul(rpushid, i);
|
||||
for(int k=0; k<wallorder; k++) {
|
||||
if(ipush == j) {
|
||||
DEBB(DF_FIELD, (debugfile, "River found at %d:%d\n", i, k));
|
||||
riverid = i;
|
||||
goto riveridfound;
|
||||
}
|
||||
j = gmul(j, wallid);
|
||||
}
|
||||
}
|
||||
|
||||
riveridfound: ;
|
||||
|
||||
W = strtomatrix("RRRRPR");
|
||||
for(int j=0; j<wallorder; j++) {
|
||||
W = mmul(W, Wall);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
if(i == 7) SETDIST(W, 0, itCoast)
|
||||
if(i == 3) SETDIST(mmul(PRRRP, W), 0, itWhirlpool)
|
||||
W = mmul(Wall, W);
|
||||
}
|
||||
}
|
||||
dijkstra(purehepta ? distriver : distflower, indist);
|
||||
|
||||
W = matrices[riverid];
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itStatue)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = mmul(P, W);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itSapphire)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = mmul(PRP, matrices[riverid]);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 1, itShard)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = mmul(PR, matrices[riverid]);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 1, itGold)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
int riverdist = dijkstra(purehepta ? distflower : distriver, indist);
|
||||
DEBB(DF_FIELD, (debugfile, "river dist = %d\n", riverdist));
|
||||
|
||||
if(!purehepta) {
|
||||
W = matrices[riverid];
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itStatue)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = mmul(PR, matrices[riverid]);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itGold)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = mmul(P, matrices[riverid]);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 1, itSapphire)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
dijkstra(distriverleft, indist);
|
||||
W = mmul(PRP, matrices[riverid]);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itShard)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = mmul(P, matrices[riverid]);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 0, itSapphire)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
W = matrices[riverid];
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
SETDIST(W, 1, itStatue)
|
||||
W = mmul(W, Wall);
|
||||
}
|
||||
dijkstra(distriverright, indist);
|
||||
}
|
||||
else {
|
||||
W = strtomatrix("RRRRPR");
|
||||
for(int j=0; j<wallorder; j++) {
|
||||
W = mmul(W, Wall);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
if(i == 7) SETDIST(W, 0, itCoast)
|
||||
W = mmul(Wall, W);
|
||||
}
|
||||
}
|
||||
dijkstra(distriverleft, indist);
|
||||
W = strtomatrix("RRRRPR");
|
||||
for(int j=0; j<wallorder; j++) {
|
||||
W = mmul(W, Wall);
|
||||
for(int i=0; i<wallorder; i++) {
|
||||
if(i == 3) SETDIST(mmul(PRRRP, W), 0, itWhirlpool)
|
||||
W = mmul(Wall, W);
|
||||
}
|
||||
}
|
||||
dijkstra(distriverright, indist);
|
||||
}
|
||||
|
||||
DEBB(DF_FIELD, (debugfile, "wall-river distance = %d\n", distwall[riverid]));
|
||||
DEBB(DF_FIELD, (debugfile, "river-wall distance = %d\n", distriver[0]));
|
||||
}
|
||||
|
||||
bool easy(int i) {
|
||||
return i < Prime || !(i % Prime);
|
||||
}
|
||||
|
||||
// 11 * 25
|
||||
// (1+z+z^3) * (1+z^3+z^4) ==
|
||||
// 1+z+z^7 == 1+z+z^2(z^5) == 1+z+z^2(1+z^2) = 1+z+z^2+z^4
|
||||
|
||||
void init(int p) {
|
||||
Prime = p;
|
||||
if(solve()) {
|
||||
printf("error: could not solve the fieldpattern\n");
|
||||
exit(1);
|
||||
}
|
||||
build();
|
||||
}
|
||||
|
||||
fpattern(int p) {
|
||||
if(!p) return;
|
||||
init(p);
|
||||
}
|
||||
|
||||
void findsubpath() {
|
||||
int N = size(matrices);
|
||||
for(int i=1; i<N; i++)
|
||||
if(gpow(i, Prime) == 0) {
|
||||
subpathid = i;
|
||||
subpathorder = Prime;
|
||||
DEBB(DF_FIELD, (debugfile, "Subpath found: %s\n", decodepath(i).c_str()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int fpattern::orderstats() {
|
||||
int N = size(matrices);
|
||||
|
||||
#define MAXORD 10000
|
||||
int ordcount[MAXORD];
|
||||
int ordsample[MAXORD];
|
||||
|
||||
for(int i=0; i<MAXORD; i++) ordcount[i] = 0;
|
||||
|
||||
for(int i=0; i<N; i++) {
|
||||
int cnt = order(matrices[i]);
|
||||
|
||||
if(cnt < MAXORD) {
|
||||
if(!ordcount[cnt]) ordsample[cnt] = i;
|
||||
ordcount[cnt]++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Listing:\n");
|
||||
for(int i=0; i<MAXORD; i++) if(ordcount[i])
|
||||
printf("Found %4d matrices of order %3d: %s\n", ordcount[i], i, decodepath(ordsample[i]).c_str());
|
||||
|
||||
return ordsample[Prime];
|
||||
}
|
||||
|
||||
|
||||
fpattern fp43(43);
|
||||
|
||||
void info() {
|
||||
fpattern fp(0);
|
||||
int cases = 0, hard = 0;
|
||||
for(int p=0; p<500; p++) {
|
||||
fp.Prime = p;
|
||||
if(fp.solve() == 0) {
|
||||
printf("%4d: wsquare=%d cs=%d sn=%d ch=%d sh=%d\n",
|
||||
p, fp.wsquare, fp.cs, fp.sn, fp.ch, fp.sh);
|
||||
cases++;
|
||||
if(!fp.easy(fp.cs) || !fp.easy(fp.sn) || !fp.easy(fp.ch) || !fp.easy(fp.sn))
|
||||
hard++;
|
||||
#ifndef EASY
|
||||
neasy = 0;
|
||||
#endif
|
||||
fp.build();
|
||||
#ifndef EASY
|
||||
printf("Not easy: %d\n", neasy);
|
||||
#endif
|
||||
int N = size(fp.matrices);
|
||||
int left = N / fp.Prime;
|
||||
printf("Prime decomposition: %d = %d", N, fp.Prime);
|
||||
for(int p=2; p<=left; p++) while(left%p == 0) printf("*%d", p), left /= p;
|
||||
printf("\n");
|
||||
printf("Order of RRP is: %d\n", fp.order(fp.strtomatrix("RRP")));
|
||||
printf("Order of RRRP is: %d\n", fp.order(fp.strtomatrix("RRRP")));
|
||||
printf("Order of RRRPRRRRRPRRRP is: %d\n", fp.order(fp.strtomatrix("RRRPRRRRRPRRRP")));
|
||||
}
|
||||
}
|
||||
printf("cases found = %d (%d hard)\n", cases, hard);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using fieldpattern::fp43;
|
224
flags.cpp
224
flags.cpp
|
@ -12,7 +12,9 @@ bool isIcyLand(cell *c) {
|
|||
}
|
||||
|
||||
bool isGravityLand(eLand l) {
|
||||
return l == laIvoryTower || l == laEndorian;
|
||||
return
|
||||
l == laIvoryTower || l == laEndorian ||
|
||||
l == laMountain || l == laDungeon;
|
||||
}
|
||||
|
||||
// watery
|
||||
|
@ -32,7 +34,8 @@ bool isWateryOrBoat(cell *c) {
|
|||
bool isNoFlight(cell *c) {
|
||||
return
|
||||
c->wall == waBoat || c->wall == waVineHalfA || c->wall == waVineHalfB ||
|
||||
c->wall == waStrandedBoat || c->wall == waTrunk;
|
||||
c->wall == waStrandedBoat || c->wall == waTrunk ||
|
||||
c->wall == waBigBush || c->wall == waSmallBush;
|
||||
}
|
||||
|
||||
bool boatStrandable(cell *c) {
|
||||
|
@ -93,7 +96,7 @@ bool isNonliving(eMonster m) {
|
|||
m == moMirage || m == moMirror || m == moGolem || m == moGolemMoved ||
|
||||
m == moZombie || m == moGhost || m == moShadow || m == moSkeleton ||
|
||||
m == moEvilGolem || m == moIllusion || m == moEarthElemental ||
|
||||
m == moWaterElemental;
|
||||
m == moWaterElemental || m == moDraugr;
|
||||
}
|
||||
|
||||
bool isMetalBeast(eMonster m) {
|
||||
|
@ -102,7 +105,8 @@ bool isMetalBeast(eMonster m) {
|
|||
|
||||
bool isStunnable(eMonster m) {
|
||||
return m == moPalace || m == moFatGuard || m == moSkeleton || isPrincess(m) ||
|
||||
isMetalBeast(m) || m == moTortoise || isDragon(m);
|
||||
isMetalBeast(m) || m == moTortoise || isDragon(m) ||
|
||||
m == moReptile;
|
||||
}
|
||||
|
||||
bool hasHitpoints(eMonster m) {
|
||||
|
@ -110,15 +114,23 @@ bool hasHitpoints(eMonster m) {
|
|||
}
|
||||
|
||||
bool isMountable(eMonster m) {
|
||||
return isWorm(m);
|
||||
return isWorm(m) && m != moTentacleGhost;
|
||||
}
|
||||
|
||||
bool isFriendly(eMonster m) {
|
||||
return isMimic(m) || isGolemOrKnight(m) || m == moIllusion;
|
||||
return isMimic(m) || isGolemOrKnight(m) || m == moIllusion || m == moFriendlyIvy;
|
||||
}
|
||||
|
||||
bool isFriendlyOrPlayer(eMonster m) {
|
||||
return isFriendly(m) || m == moPlayer;
|
||||
}
|
||||
|
||||
bool isFriendly(cell *c) {
|
||||
if(items[itOrbDomination] && c->monst && sameMonster(c, cwt.c)) return true;
|
||||
if(items[itOrbDomination] && c->monst && c->monst != moTentacleGhost) {
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
if(sameMonster(c, playerpos(i)))
|
||||
return true;
|
||||
}
|
||||
return isFriendly(c->monst);
|
||||
}
|
||||
|
||||
|
@ -146,13 +158,18 @@ bool isIvy(cell *c) {
|
|||
}
|
||||
|
||||
bool isMonsterPart(eMonster m) {
|
||||
return m == moMutant || (isIvy(m) && m != moIvyRoot);
|
||||
return m == moMutant || (isIvy(m) && m != moIvyRoot) ||
|
||||
m == moDragonTail || m == moKrakenT;
|
||||
}
|
||||
|
||||
bool isMutantIvy(eMonster m) {
|
||||
return m == moMutant;
|
||||
}
|
||||
|
||||
bool isAnyIvy(eMonster m) {
|
||||
return isIvy(m) || isMutantIvy(m) || m == moFriendlyIvy;
|
||||
}
|
||||
|
||||
bool isBulletType(eMonster m) {
|
||||
return
|
||||
m == moBullet || m == moFlailBullet ||
|
||||
|
@ -213,7 +230,7 @@ bool cellHalfvine(cell *c) {
|
|||
}
|
||||
|
||||
bool isWarped(eLand l) {
|
||||
return l == laGridCoast || l == laGridSea;
|
||||
return l == laWarpCoast || l == laWarpSea;
|
||||
}
|
||||
|
||||
bool isElementalShard(eItem i) {
|
||||
|
@ -229,19 +246,28 @@ eMonster elementalOf(eLand l) {
|
|||
return moNone;
|
||||
}
|
||||
|
||||
eItem localshardof(eLand l) {
|
||||
return eItem(itFireShard + (l - laEFire));
|
||||
}
|
||||
|
||||
int itemclass(eItem i) {
|
||||
if(i == 0) return -1;
|
||||
if(i < itKey || i == itFernFlower ||
|
||||
i == itWine || i == itSilver || i == itEmerald || i == itRoyalJelly || i == itPower ||
|
||||
i == itGrimoire || i == itPirate || i == itRedGem || i == itBombEgg ||
|
||||
i == itCoast || i == itWhirlpool || i == itPalace || i == itFjord ||
|
||||
i == itElemental || i == itZebra || i == itEdge ||
|
||||
i == itElemental || i == itZebra || i == itIvory ||
|
||||
i == itBounty || i == itFulgurite || i == itMutant || i == itLotus || i == itMutant2 ||
|
||||
i == itWindstone || i == itCoral || i == itRose ||
|
||||
i == itBabyTortoise || i == itDragon || i == itApple)
|
||||
i == itBabyTortoise || i == itDragon || i == itApple ||
|
||||
i == itKraken || i == itBarrow || i == itTrollEgg || i == itTreat ||
|
||||
i == itSlime || i == itAmethyst || i == itDodeca ||
|
||||
i == itGreenGrass || i == itBull)
|
||||
return IC_TREASURE;
|
||||
if(i == itSavedPrincess || i == itStrongWind || i == itWarning)
|
||||
return IC_NAI;
|
||||
if(i == itKey || i == itOrbYendor || i == itGreenStone || i == itHolyGrail || i == itCompass ||
|
||||
i == itSavedPrincess || isElementalShard(i) || i == itRevolver || i == itStrongWind)
|
||||
isElementalShard(i) || i == itRevolver)
|
||||
return IC_OTHER;
|
||||
return IC_ORB;
|
||||
}
|
||||
|
@ -264,10 +290,11 @@ bool realred(eWall w) {
|
|||
|
||||
int snakelevel(eWall w) {
|
||||
if(w == waRed1 || w == waDeadfloor2 || w == waRubble || w == waGargoyleFloor ||
|
||||
w == waGargoyleBridge || w == waTempFloor || w == waTempBridge)
|
||||
w == waGargoyleBridge || w == waTempFloor || w == waTempBridge || w == waRoundTable)
|
||||
return 1;
|
||||
if(w == waRed2) return 2;
|
||||
if(w == waRed3) return 3;
|
||||
if(w == waTower) return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -285,7 +312,9 @@ bool isWall(cell *w) {
|
|||
w->wall == waStrandedBoat || w->wall == waOpenGate || w->wall == waClosePlate ||
|
||||
w->wall == waOpenPlate || w->wall == waTrapdoor || w->wall == waGiantRug ||
|
||||
w->wall == waLadder || w->wall == waTrunk || w->wall == waSolidBranch ||
|
||||
w->wall == waWeakBranch || w->wall == waCanopy)
|
||||
w->wall == waWeakBranch || w->wall == waCanopy || w->wall == waTower ||
|
||||
w->wall == waSmallBush || w->wall == waBigBush ||
|
||||
w->wall == waReptile || w->wall == waReptileBridge)
|
||||
return false;
|
||||
if(isWatery(w) || isChasmy(w) || isFire(w)) return false;
|
||||
return true;
|
||||
|
@ -293,18 +322,25 @@ bool isWall(cell *w) {
|
|||
|
||||
bool isAngryBird(eMonster m) {
|
||||
return m == moEagle || m == moAlbatross || m == moBomberbird || m == moGargoyle ||
|
||||
m == moWindCrow || m == moKestrel || m == moNighthawk;
|
||||
m == moWindCrow || m == moSparrowhawk ||
|
||||
m == moVampire || m == moBat || m == moButterfly || m == moGadfly;
|
||||
}
|
||||
|
||||
bool isBird(eMonster m) {
|
||||
return isAngryBird(m) || m == moTameBomberbird || m == moTameBomberbirdMoved;
|
||||
return isAngryBird(m) || m == moTameBomberbird || m == moTameBomberbirdMoved;
|
||||
}
|
||||
|
||||
bool slowMover(eMonster m) {
|
||||
return
|
||||
m == moLesser || m == moGreater || isMetalBeast(m) ||
|
||||
m == moTortoise || m == moDraugr;
|
||||
}
|
||||
|
||||
bool normalMover(eMonster m) {
|
||||
return
|
||||
m == moYeti || m == moRanger || m == moGoblin || m == moTroll || m == moDesertman ||
|
||||
m == moMonkey || m == moZombie || m == moNecromancer || m == moCultist ||
|
||||
m == moLesser || m == moGreater || m == moRunDog || m == moPyroCultist ||
|
||||
m == moRunDog || m == moPyroCultist ||
|
||||
m == moFireFairy || m == moCrystalSage || m == moHedge ||
|
||||
m == moVineBeast || m == moLancer || m == moFlailer ||
|
||||
m == moMiner || m == moDarkTroll ||
|
||||
|
@ -314,12 +350,12 @@ bool normalMover(eMonster m) {
|
|||
m == moRedTroll ||
|
||||
m == moPalace || m == moFatGuard || m == moSkeleton || m == moVizier ||
|
||||
m == moFjordTroll || m == moStormTroll || m == moForestTroll ||
|
||||
m == moEdgeMonkey ||
|
||||
m == moFireElemental || m == moOrangeDog ||
|
||||
isMetalBeast(m) ||
|
||||
m == moFamiliar ||
|
||||
m == moFireElemental || m == moOrangeDog ||
|
||||
m == moOutlaw || m == moRedFox || m == moFalsePrincess || m == moRoseLady ||
|
||||
m == moRoseBeauty || m == moWolf ||
|
||||
m == moTortoise || m == moLemur;
|
||||
m == moResearcher || m == moRagingBull ||
|
||||
slowMover(m);
|
||||
}
|
||||
|
||||
// from-to
|
||||
|
@ -339,20 +375,24 @@ bool isShark(eMonster m) {
|
|||
|
||||
bool isSlimeMover(eMonster m) {
|
||||
return
|
||||
m == moSlime || m == moSeep || m == moShark ||
|
||||
m == moVineSpirit || m == moCShark || m == moParrot;
|
||||
m == moSlime || m == moSeep || m == moVineSpirit || m == moParrot;
|
||||
}
|
||||
|
||||
bool isDragon(eMonster m) { return m == moDragonHead || m == moDragonTail; }
|
||||
|
||||
bool isKraken(eMonster m) { return m == moKrakenH || m == moKrakenT; }
|
||||
|
||||
bool isBlowableMonster(eMonster m) {
|
||||
return m && !(
|
||||
isWorm(m) || isIvy(m) || isMutantIvy(m) || isSlimeMover(m) ||
|
||||
m == moGhost || m == moGreaterShark ||
|
||||
m == moWaterElemental || m == moWitchGhost || isMimic(m)
|
||||
m == moWaterElemental || m == moWitchGhost || isMimic(m) ||
|
||||
isKraken(m)
|
||||
);
|
||||
}
|
||||
|
||||
bool isMultitile(eMonster m) {
|
||||
return isWorm(m) || isIvy(m) || isMutantIvy(m);
|
||||
return isWorm(m) || isIvy(m) || isMutantIvy(m) || isKraken(m);
|
||||
}
|
||||
|
||||
bool isSlimeMover(cell *c) {
|
||||
|
@ -380,8 +420,7 @@ bool isLeader(eMonster m) {
|
|||
}
|
||||
|
||||
bool isFlying(eMonster m) {
|
||||
return isBird(m) || isGhost(m) || m == moAirElemental || isDragon(m) ||
|
||||
(isFriendly(m) && checkOrb(m, itOrbGhost));
|
||||
return isBird(m) || isGhost(m) || m == moAirElemental || isDragon(m) || checkOrb(m, itOrbAether);
|
||||
}
|
||||
|
||||
bool survivesChasm(eMonster m) {
|
||||
|
@ -393,7 +432,7 @@ bool ignoresPlates(eMonster m) {
|
|||
}
|
||||
|
||||
bool itemBurns(eItem it) {
|
||||
return it && it != itOrbDragon && it != itOrbFire && it != itDragon;
|
||||
return it && it != itOrbDragon && it != itOrbFire && it != itDragon && it != itTreat;
|
||||
}
|
||||
|
||||
bool attackThruVine(eMonster m) {
|
||||
|
@ -404,6 +443,11 @@ bool attackNonAdjacent(eMonster m) {
|
|||
return m == moGhost || m == moFriendlyGhost || m == moTentacleGhost;
|
||||
}
|
||||
|
||||
bool noHighlight(eMonster m) {
|
||||
return
|
||||
(m == moIvyWait || m == moIvyNext || m == moIvyDead);
|
||||
}
|
||||
|
||||
bool isInactiveEnemy(cell *w, eMonster forwho) {
|
||||
if(w->monst == moWormtail || w->monst == moWormwait || w->monst == moTentacletail || w->monst == moTentaclewait || w->monst == moHexSnakeTail)
|
||||
return true;
|
||||
|
@ -429,7 +473,7 @@ bool isActiveEnemy(cell *w, eMonster forwho) {
|
|||
bool isUnarmed(eMonster m) {
|
||||
return
|
||||
m == moMouse || m == moMouseMoved || m == moPrincess || m == moPrincessMoved ||
|
||||
m == moCrystalSage;
|
||||
m == moCrystalSage || m == moVampire || m == moBat;
|
||||
}
|
||||
|
||||
bool isArmedEnemy(cell *w, eMonster forwho) {
|
||||
|
@ -451,16 +495,17 @@ bool eternalFire(cell *c) {
|
|||
|
||||
bool isCyclic(eLand l) {
|
||||
return
|
||||
l == laWhirlpool || l == laTemple || l == laCamelot || l == laClearing;
|
||||
l == laWhirlpool || l == laTemple || l == laCamelot || l == laClearing ||
|
||||
l == laMountain;
|
||||
}
|
||||
|
||||
bool haveRangedOrb() {
|
||||
return
|
||||
items[itOrbPsi] || items[itOrbDragon] || items[itOrbTeleport] ||
|
||||
items[itOrbIllusion] || items[itOrbTelekinesis] || items[itOrbAir] ||
|
||||
items[itOrbIllusion] || items[itOrbSpace] || items[itOrbAir] ||
|
||||
items[itOrbFrog] || items[itOrbSummon] || items[itOrbMatter] ||
|
||||
items[itRevolver] || items[itOrbStunning] || items[itStrongWind] ||
|
||||
items[itOrbDomination];
|
||||
items[itOrbDomination] || items[itOrbNature] || items[itOrbDash];
|
||||
}
|
||||
|
||||
bool isOffensiveOrb(eItem it) {
|
||||
|
@ -471,9 +516,9 @@ bool isOffensiveOrb(eItem it) {
|
|||
|
||||
bool isRangedOrb(eItem i) {
|
||||
return i == itOrbPsi || i == itOrbDragon || i == itOrbTeleport || i == itOrbIllusion ||
|
||||
i == itOrbTelekinesis || i == itOrbAir || i == itOrbFrog ||
|
||||
i == itOrbSpace || i == itOrbAir || i == itOrbFrog ||
|
||||
i == itOrbSummon || i == itOrbMatter || i == itRevolver || i == itOrbStunning ||
|
||||
i == itOrbDomination;
|
||||
i == itOrbDomination || i == itOrbNature || i == itOrbDash;
|
||||
}
|
||||
|
||||
bool isProtectionOrb(eItem i) {
|
||||
|
@ -484,59 +529,72 @@ bool isEmpathyOrb(eItem i) {
|
|||
return
|
||||
i == itOrbFire || i == itOrbDigging || i == itOrbWinter ||
|
||||
i == itOrbUndeath || i == itOrbSpeed || i == itOrbShield ||
|
||||
i == itOrbGhost || i == itOrbInvis || i == itOrbThorns ||
|
||||
i == itOrbWater;
|
||||
i == itOrbAether || i == itOrbInvis || i == itOrbThorns ||
|
||||
i == itOrbWater || i == itOrbStone;
|
||||
}
|
||||
|
||||
bool isUtilityOrb(eItem i) {
|
||||
return i == itOrbSpeed || i == itOrbDigging ||
|
||||
i == itOrbSafety || i == itOrbTeleport || i == itOrbGhost ||
|
||||
i == itOrbPreserve || i == itOrbTelekinesis ||
|
||||
i == itOrbSafety || i == itOrbTeleport || i == itOrbAether ||
|
||||
i == itOrbTime || i == itOrbSpace ||
|
||||
i == itOrbSummon || i == itOrbLuck || i == itOrbEnergy;
|
||||
}
|
||||
|
||||
bool isDirectionalOrb(eItem i) {
|
||||
return i == itOrbHorns || i == itOrbBull;
|
||||
}
|
||||
|
||||
bool isRevivalOrb(eItem i) {
|
||||
return i == itOrbLife || i == itOrbFriend || i == itOrbUndeath;
|
||||
}
|
||||
|
||||
bool isFriendOrb(eItem i) {
|
||||
return i == itOrbLife || i == itOrbFriend || i == itOrbDiscord || i == itOrbLove ||
|
||||
i == itOrbEmpathy || i == itOrbUndeath;
|
||||
}
|
||||
|
||||
bool isFriendlyGhost(eMonster m) {
|
||||
return m == moFriendlyGhost || (markEmpathy(itOrbGhost) && isFriendly(m));
|
||||
return m == moFriendlyGhost || (markEmpathy(itOrbAether) && isFriendly(m));
|
||||
}
|
||||
|
||||
bool isDragon(eMonster m) { return m == moDragonHead || m == moDragonTail; }
|
||||
|
||||
bool survivesWater(eMonster m) {
|
||||
return
|
||||
m == moShark || m == moGreaterShark || m == moCShark ||
|
||||
isGhost(m) || m == moWitchGhost ||
|
||||
isGhost(m) || m == moWitchGhost || m == moShadow ||
|
||||
isBird(m) || m == moWaterElemental || m == moAirElemental ||
|
||||
isWorm(m) || isIvy(m) || isDragon(m) ||
|
||||
isWorm(m) || isIvy(m) || isDragon(m) || isKraken(m) ||
|
||||
m == moMutant || m == moFriendlyIvy ||
|
||||
m == moTortoise; // Tortoises and Ivies survive, but don't go through water
|
||||
}
|
||||
|
||||
// flying even if stunned
|
||||
bool isPermanentFlying(eMonster m) {
|
||||
return m == moAirElemental || isGhost(m);
|
||||
}
|
||||
|
||||
bool survivesFire(eMonster m) {
|
||||
return
|
||||
isGhost(m) || m == moWitchWinter || m == moWitchGhost ||
|
||||
m == moBomberbird || m == moTameBomberbird || m == moTameBomberbirdMoved ||
|
||||
(isFriendly(m) && markOrb(itOrbWinter)) || isWorm(m) || m == moFireElemental ||
|
||||
isDragon(m);
|
||||
isDragon(m) || m == moShadow;
|
||||
}
|
||||
|
||||
bool survivesMine(eMonster m) {
|
||||
return isFlying(m);
|
||||
}
|
||||
/* bool survivesMine(eMonster m) {
|
||||
return ignoresPlates(m) || isFlying(m);
|
||||
} */
|
||||
|
||||
bool survivesWall(eMonster m) {
|
||||
return isGhost(m);
|
||||
}
|
||||
|
||||
bool survivesThorns(eMonster m) {
|
||||
return isGhost(m) || m == moSkeleton;
|
||||
return isGhost(m) || m == moSkeleton || m == moDraugr;
|
||||
}
|
||||
|
||||
bool survivesFall(eMonster m) {
|
||||
return isBird(m) || m == moAirElemental || m == moSkeleton || isDragon(m);
|
||||
return isBird(m) || m == moAirElemental || m == moSkeleton || isDragon(m) || m == moShadow ||
|
||||
isGhost(m);
|
||||
}
|
||||
|
||||
bool isThorny(eWall w) { return w == waRose; }
|
||||
|
@ -547,9 +605,75 @@ bool checkOrb(eMonster m1, eItem orb) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool checkOrb2(eMonster m1, eItem orb) {
|
||||
if(m1 == moPlayer) return markOrb2(orb);
|
||||
if(isFriendly(m1)) return markEmpathy2(orb);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ignoresSmell(eMonster m) {
|
||||
return
|
||||
m == moHexSnake || isIvy(m) || isMutantIvy(m) || isGhostMover(m) || isSlimeMover(m) ||
|
||||
m == moRoseLady || checkOrb(m, itOrbSkunk) || checkOrb(m, itOrbGhost) || checkOrb(m, itOrbShield);
|
||||
m == moRoseLady || checkOrb(m, itOrbBeauty) || checkOrb(m, itOrbAether) || checkOrb(m, itOrbShield);
|
||||
}
|
||||
|
||||
bool isTroll(eMonster m) {
|
||||
return
|
||||
m == moTroll || m == moRedTroll || m == moDarkTroll ||
|
||||
m == moForestTroll || m == moStormTroll || m == moFjordTroll;
|
||||
}
|
||||
|
||||
bool isGrave(eWall w) {
|
||||
return w == waFreshGrave || w == waAncientGrave;
|
||||
}
|
||||
|
||||
bool isTree(cell *c) {
|
||||
return false; // c->wall == waBigTree || c->wall == waSmallTree;
|
||||
}
|
||||
|
||||
bool highwall(cell *c) {
|
||||
if(c->wall == waGlass) return false;
|
||||
if(wmescher && wmspatial && c->wall == waBarrier && c->land == laOceanWall)
|
||||
return false;
|
||||
// if(wmspatial && isTree(c)) return false;
|
||||
if(isGrave(c->wall)) return true;
|
||||
return winf[c->wall].glyph == '#' || c->wall == waClosedGate;
|
||||
}
|
||||
|
||||
int chasmgraph(cell *c) {
|
||||
if(c->wall == waChasm) return 2;
|
||||
if(isChasmy(c)) return 1;
|
||||
if(isWateryOrBoat(c)) return 1;
|
||||
if(wmescher && c->wall == waBarrier && c->land == laOceanWall) return 1;
|
||||
if(c->wall == waReptileBridge) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool conegraph(cell *c) {
|
||||
return wmescher && wmspatial && (c->wall == waDune || c->wall == waBigTree || c->wall == waSmallTree || c->wall == waCTree || (c->wall == waBarrier && c->land == laOceanWall));
|
||||
}
|
||||
|
||||
bool isReptile(eWall w) {
|
||||
return w == waReptile || w == waReptileBridge;
|
||||
}
|
||||
|
||||
bool isBull(eMonster m) {
|
||||
return m == moRagingBull || m == moHerdBull || m == moSleepBull;
|
||||
}
|
||||
|
||||
bool hornStuns(cell *c) {
|
||||
eMonster m = c->monst;
|
||||
return
|
||||
m == moRagingBull || m == moSleepBull || m == moHerdBull ||
|
||||
m == moButterfly || m == moGreater || m == moGreaterM || m == moDraugr ||
|
||||
m == moHedge || m == moFlailer || m == moVizier ||
|
||||
attackJustStuns(c);
|
||||
}
|
||||
|
||||
// generate all the world first in the quotient geometry
|
||||
bool generateAll(eLand l) {
|
||||
return
|
||||
l == laIce || l == laDryForest || l == laCocytus || l == laLivefjord ||
|
||||
l == laCaves || l == laCA;
|
||||
}
|
||||
|
||||
|
|
244
geometry.cpp
244
geometry.cpp
|
@ -4,21 +4,33 @@
|
|||
// Copyright (C) 2011-2012 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
|
||||
ld tessf, crossf, hexf, hcrossf;
|
||||
ld tessf, crossf, hexf, hcrossf, hexhexdist;
|
||||
|
||||
// tessf: distance from heptagon center to another heptagon center
|
||||
// hexf: distance from heptagon center to heptagon vertex
|
||||
// crossf: distance from heptagon center to adjacent hexagon center
|
||||
// hexhexdist: distance between adjacent hexagon vertices
|
||||
|
||||
#define ALPHA (M_PI*2/7)
|
||||
#define ALPHA (M_PI*2/S7)
|
||||
|
||||
hyperpoint Crad[42];
|
||||
|
||||
transmatrix heptmove[7], hexmove[7];
|
||||
transmatrix invheptmove[7], invhexmove[7];
|
||||
|
||||
transmatrix spinmatrix[84];
|
||||
|
||||
const transmatrix& getspinmatrix(int id) {
|
||||
while(id>=S84) id -= S84;
|
||||
while(id<0) id += S84;
|
||||
return spinmatrix[id];
|
||||
}
|
||||
|
||||
// the results are:
|
||||
// hexf = 0.378077 hcrossf = 0.620672 tessf = 1.090550
|
||||
// hexhexdist = 0.566256
|
||||
|
||||
// the distance between two hexagon centers
|
||||
|
||||
void precalc() {
|
||||
|
||||
|
@ -31,15 +43,15 @@ void precalc() {
|
|||
for(int p=0; p<100; p++) {
|
||||
ld f = (fmin+fmax) / 2;
|
||||
hyperpoint H = xpush(f) * C0;
|
||||
ld v1 = intval(H, C0), v2 = intval(H, spin(2*M_PI/7)*H);
|
||||
if(v1 > v2) fmin = f; else fmax = f;
|
||||
ld v1 = intval(H, C0), v2 = intval(H, spin(2*M_PI/S7)*H);
|
||||
if(sphere ? v1 < v2 : v1 > v2) fmin = f; else fmax = f;
|
||||
}
|
||||
tessf = fmin;
|
||||
|
||||
fmin = 0, fmax = 2;
|
||||
fmin = 0, fmax = sphere ? M_PI / 2 : 2;
|
||||
for(int p=0; p<100; p++) {
|
||||
ld f = (fmin+fmax) / 2;
|
||||
hyperpoint H = spin(M_PI/7) * xpush(f) * C0;
|
||||
hyperpoint H = spin(M_PI/S7) * xpush(f) * C0;
|
||||
ld v1 = intval(H, C0), v2 = intval(H, xpush(tessf) * C0);
|
||||
if(v1 < v2) fmin = f; else fmax = f;
|
||||
}
|
||||
|
@ -50,7 +62,7 @@ void precalc() {
|
|||
for(int p=0; p<100; p++) {
|
||||
ld f = (fmin+fmax) / 2;
|
||||
hyperpoint H = xpush(f) * C0;
|
||||
hyperpoint H1 = spin(2*M_PI/7) * H;
|
||||
hyperpoint H1 = spin(2*M_PI/S7) * H;
|
||||
hyperpoint H2 = xpush(tessf-f) * C0;
|
||||
ld v1 = intval(H, H1), v2 = intval(H, H2);
|
||||
if(v1 < v2) fmin = f; else fmax = f;
|
||||
|
@ -59,84 +71,180 @@ void precalc() {
|
|||
|
||||
// printf("hexf = %.6Lf cross = %.6Lf tessf = %.6Lf\n", hexf, crossf, tessf);
|
||||
|
||||
for(int i=0; i<42; i++)
|
||||
Crad[i] = spin(2*M_PI*i/42) * xpush(.4) * C0;
|
||||
for(int d=0; d<7; d++)
|
||||
for(int i=0; i<S42; i++)
|
||||
Crad[i] = spin(2*M_PI*i/S42) * xpush(.4) * C0;
|
||||
for(int d=0; d<S7; d++)
|
||||
heptmove[d] = spin(-d * ALPHA) * xpush(tessf) * spin(M_PI);
|
||||
for(int d=0; d<7; d++)
|
||||
for(int d=0; d<S7; d++)
|
||||
hexmove[d] = spin(-d * ALPHA) * xpush(-crossf)* spin(M_PI);
|
||||
|
||||
for(int d=0; d<7; d++) invheptmove[d] = inverse(heptmove[d]);
|
||||
for(int d=0; d<7; d++) invhexmove[d] = inverse(hexmove[d]);
|
||||
for(int d=0; d<S7; d++) invheptmove[d] = inverse(heptmove[d]);
|
||||
for(int d=0; d<S7; d++) invhexmove[d] = inverse(hexmove[d]);
|
||||
|
||||
hexhexdist = hdist(xpush(crossf) * C0, spin(M_PI*2/S7) * xpush(crossf) * C0);
|
||||
|
||||
for(int i=0; i<S84; i++) spinmatrix[i] = spin(i * M_PI / S42);
|
||||
}
|
||||
|
||||
transmatrix ddi(ld dir, ld dist) {
|
||||
// EUCLIDEAN
|
||||
if(euclid)
|
||||
return eupush(cos(M_PI*dir/42) * dist, -sin(M_PI*dir/42) * dist);
|
||||
return eupush(cos(M_PI*dir/S42) * dist, -sin(M_PI*dir/S42) * dist);
|
||||
else
|
||||
return spin(M_PI*dir/42) * xpush(dist) * spin(-M_PI*dir/42);
|
||||
return spin(M_PI*dir/S42) * xpush(dist) * spin(-M_PI*dir/S42);
|
||||
}
|
||||
|
||||
// tesselation drawing
|
||||
hyperpoint ddi0(ld dir, ld dist) {
|
||||
if(euclid)
|
||||
return hpxy(cos(M_PI*dir/S42) * dist, -sin(M_PI*dir/S42) * dist);
|
||||
else
|
||||
return xspinpush0(M_PI*dir/S42, dist);
|
||||
}
|
||||
|
||||
#define NUMFACE 500
|
||||
transmatrix tess[NUMFACE];
|
||||
namespace geom3 {
|
||||
|
||||
void genTesselation() {
|
||||
int N = 1;
|
||||
tess[0] = Id;
|
||||
for(int i=0; i<N; i++) {
|
||||
for(int t=0; t<7; t++) {
|
||||
ld trot = (t % 8) * M_PI * 2 / 7.0;
|
||||
transmatrix T = spin(trot) * xpush(tessf) * /*spin(-trot) */ spin(M_PI) * tess[i];
|
||||
for(int j=0; j<N; j++) if(intval(T*C0, tess[j]*C0) < 0.1) goto nextt;
|
||||
// printf("%d:%d -> %d\n", i,t, N);
|
||||
tess[N] = T; N++;
|
||||
if(N == NUMFACE) return;
|
||||
nextt: ;
|
||||
int tc_alpha=3, tc_depth=1, tc_camera=2;
|
||||
|
||||
ld depth = 1; // world below the plane
|
||||
ld camera = 1; // camera above the plane
|
||||
ld wall_height = .3;
|
||||
ld slev = .08;
|
||||
ld lake_top = .25, lake_bottom = .9;
|
||||
ld rock_wall_ratio = .9;
|
||||
ld human_wall_ratio = .7;
|
||||
ld human_height;
|
||||
|
||||
ld highdetail = 8, middetail = 8;
|
||||
|
||||
// Here we convert between the following parameters:
|
||||
|
||||
// abslev: level below the plane
|
||||
// lev: level above the world (abslev = depth-lev)
|
||||
// projection: projection parameter
|
||||
// factor: zoom factor
|
||||
|
||||
ld abslev_to_projection(ld abslev) {
|
||||
if(sphere || euclid) return camera+abslev;
|
||||
return tanh(abslev) / tanh(camera);
|
||||
}
|
||||
|
||||
ld projection_to_abslev(ld proj) {
|
||||
if(sphere || euclid) return proj-camera;
|
||||
// tanh(abslev) / tanh(camera) = proj
|
||||
return atanh(proj * tanh(camera));
|
||||
}
|
||||
|
||||
ld lev_to_projection(ld lev) {
|
||||
return abslev_to_projection(depth - lev);
|
||||
}
|
||||
|
||||
ld projection_to_factor(ld proj) {
|
||||
return lev_to_projection(0) / proj;
|
||||
}
|
||||
|
||||
ld factor_to_projection(ld fac) {
|
||||
return lev_to_projection(0) / fac;
|
||||
}
|
||||
|
||||
ld lev_to_factor(ld lev) {
|
||||
return projection_to_factor(lev_to_projection(lev));
|
||||
}
|
||||
ld factor_to_lev(ld fac) {
|
||||
return depth - projection_to_abslev(factor_to_projection(fac));
|
||||
}
|
||||
|
||||
// how should we scale at level lev
|
||||
ld scale_at_lev(ld lev) {
|
||||
if(sphere || euclid) return 1;
|
||||
return cosh(depth - lev);
|
||||
}
|
||||
|
||||
ld INFDEEP, BOTTOM, HELLSPIKE, LAKE, WALL,
|
||||
SLEV[4], FLATEYE,
|
||||
LEG1, LEG, LEG3, GROIN, GROIN1, GHOST,
|
||||
BODY, NECK1, NECK, NECK3, HEAD,
|
||||
ABODY, AHEAD, BIRD;
|
||||
|
||||
string invalid;
|
||||
|
||||
void compute() {
|
||||
// tanh(depth) / tanh(camera) == vid.alpha
|
||||
invalid = "";
|
||||
|
||||
if(tc_alpha < tc_depth && tc_alpha < tc_camera)
|
||||
vid.alpha = tanh(depth) / tanh(camera);
|
||||
else if(tc_depth < tc_alpha && tc_depth < tc_camera) {
|
||||
ld v = vid.alpha * tanh(camera);
|
||||
if(v<-1 || v>1) invalid = "cannot adjust depth", depth = camera;
|
||||
else depth = atanh(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ltd {
|
||||
hyperpoint P1;
|
||||
hyperpoint P2;
|
||||
int col;
|
||||
};
|
||||
|
||||
vector<ltd> lines;
|
||||
|
||||
void addline(hyperpoint P1, hyperpoint P2, int col) {
|
||||
ltd L;
|
||||
L.P1 = P1; L.P2 = P2; L.col = col;
|
||||
lines.push_back(L);
|
||||
}
|
||||
|
||||
void addlines() {
|
||||
|
||||
// change the if(0) conditions to see the underlying structure
|
||||
else {
|
||||
ld v = tanh(depth) / vid.alpha;
|
||||
if(v<-1 || v>1) invalid = "cannot adjust camera", camera = depth;
|
||||
else camera = atanh(v);
|
||||
}
|
||||
|
||||
if(fabs(vid.alpha) < 1e-6) invalid = "does not work with perfect Klein";
|
||||
|
||||
if(0) for(int t =0; t<NUMFACE; t++) for(int u=1; u<8; u++) {
|
||||
addline(View * tess[t] * C0, View * tess[t] * tess[u] * C0, u==1 ? 0xA000 : 0x4000);
|
||||
}
|
||||
|
||||
if(0) for(int t =0; t<NUMFACE; t++) for(int r=0; r<7; r++) {
|
||||
addline(
|
||||
View * tess[t] * spin((2*r+1)*M_PI/7) * xpush(crossf) * C0,
|
||||
View * tess[t] * spin((2*r+3)*M_PI/7) * xpush(crossf) * C0,
|
||||
0x808080);
|
||||
}
|
||||
|
||||
if(1) for(int t =0; t<NUMFACE; t++) for(int r=0; r<7; r++) {
|
||||
addline(tess[t] * spin(M_PI*2*(r+1)/7) * xpush(hexf) * C0, tess[t] * spin(M_PI*2*r/7) * xpush(hexf) * C0, 0x404040);
|
||||
addline(tess[t] * spin(M_PI*2*r/7) * xpush(hexf) * C0, tess[t] * spin(M_PI*2*r/7) * xpush(tessf/2) * C0, 0x404040);
|
||||
}
|
||||
if(invalid != "") {
|
||||
INFDEEP = .7;
|
||||
BOTTOM = .8;
|
||||
HELLSPIKE = .85;
|
||||
LAKE = .9;
|
||||
WALL = 1.25;
|
||||
SLEV[0] = 1;
|
||||
SLEV[1] = 1.08;
|
||||
SLEV[2] = 1.16;
|
||||
SLEV[3] = 1.24;
|
||||
FLATEYE = 1.03;
|
||||
LEG1 = 1.025;
|
||||
LEG = 1.05;
|
||||
LEG3 = 1.075;
|
||||
GROIN = 1.09;
|
||||
GROIN1 = 1.105;
|
||||
GHOST = 1.1;
|
||||
BODY = 1.15;
|
||||
NECK1 = 1.16;
|
||||
NECK = 1.17;
|
||||
NECK3 = 1.18;
|
||||
HEAD = 1.19;
|
||||
ABODY = 1.08;
|
||||
AHEAD = 1.12;
|
||||
BIRD = 1.20;
|
||||
}
|
||||
else {
|
||||
INFDEEP = (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(camera);
|
||||
WALL = lev_to_factor(wall_height);
|
||||
|
||||
human_height = human_wall_ratio * wall_height;
|
||||
|
||||
LEG1 = lev_to_factor(human_height * .1);
|
||||
LEG = lev_to_factor(human_height * .2);
|
||||
LEG3 = lev_to_factor(human_height * .3);
|
||||
GROIN = lev_to_factor(human_height * .4);
|
||||
GROIN1= lev_to_factor(human_height * .5);
|
||||
BODY = lev_to_factor(human_height * .6);
|
||||
NECK1 = lev_to_factor(human_height * .7);
|
||||
NECK = lev_to_factor(human_height * .8);
|
||||
NECK3 = lev_to_factor(human_height * .9);
|
||||
HEAD = lev_to_factor(human_height);
|
||||
|
||||
ABODY = lev_to_factor(human_height * .4);
|
||||
AHEAD = lev_to_factor(human_height * .6);
|
||||
BIRD = lev_to_factor((human_wall_ratio+1)/2 * wall_height * .8);
|
||||
GHOST = lev_to_factor(human_height * .5);
|
||||
FLATEYE = lev_to_factor(human_height * .15);
|
||||
|
||||
slev = rock_wall_ratio * wall_height / 3;
|
||||
for(int s=0; s<=3; s++)
|
||||
SLEV[s] = lev_to_factor(rock_wall_ratio * wall_height * s/3);
|
||||
LAKE = lev_to_factor(-lake_top);
|
||||
HELLSPIKE = lev_to_factor(-(lake_top+lake_bottom)/2);
|
||||
BOTTOM = lev_to_factor(-lake_bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initgeo() {
|
||||
// printf("%Lf\n", (ld) hdist0(xpush(-1)*ypush(0.01)*xpush(1)*C0));
|
||||
precalc();
|
||||
genTesselation();
|
||||
addlines();
|
||||
}
|
||||
|
|
111
heptagon.cpp
111
heptagon.cpp
|
@ -4,24 +4,42 @@
|
|||
// heptagon here refers to underlying heptagonal tesselation
|
||||
// (which you can see by changing the conditions in graph.cpp)
|
||||
|
||||
// automaton state
|
||||
enum hstate { hsOrigin, hsA, hsB, hsError };
|
||||
#define MIRR(x) x.mirrored
|
||||
|
||||
int fixrot(int a) { return (a+98)% 7; }
|
||||
int fix42(int a) { return (a+420)% 42; }
|
||||
// automaton state
|
||||
enum hstate { hsOrigin, hsA, hsB, hsError, hsA0, hsA1, hsB0, hsB1, hsC };
|
||||
|
||||
int fixrot(int a) { return (a+490)% S7; }
|
||||
int fix42(int a) { return (a+420)% S42; }
|
||||
|
||||
struct heptagon;
|
||||
|
||||
struct cell;
|
||||
cell *newCell(int type, heptagon *master);
|
||||
|
||||
#define CDATA
|
||||
// spintable functions
|
||||
|
||||
int tspin(uint32_t& t, int d) {
|
||||
return (t >> (d<<2)) & 7;
|
||||
}
|
||||
|
||||
int tmirror(uint32_t& t, int d) {
|
||||
return (t >> ((d<<2)+3)) & 1;
|
||||
}
|
||||
|
||||
void tsetspin(uint32_t& t, int d, int spin) {
|
||||
t &= ~(15 << (d<<2));
|
||||
t |= spin << (d<<2);
|
||||
}
|
||||
|
||||
struct heptagon {
|
||||
// automaton state
|
||||
hstate s : 8;
|
||||
// we are spin[i]-th neighbor of move[i]
|
||||
unsigned char spin[7];
|
||||
uint32_t spintable;
|
||||
int spin(int d) { return tspin(spintable, d); }
|
||||
int mirror(int d) { return tmirror(spintable, d); }
|
||||
void setspin(int d, int sp) { tsetspin(spintable, d, sp); }
|
||||
// neighbors; move[0] always goes towards origin,
|
||||
// and then we go clockwise
|
||||
heptagon* move[7];
|
||||
|
@ -33,18 +51,18 @@ struct heptagon {
|
|||
short fiftyval;
|
||||
// zebra generator (1B actually)
|
||||
short zebraval;
|
||||
#ifdef CDATA
|
||||
// field id
|
||||
int fieldval;
|
||||
// evolution data
|
||||
short rval0, rval1;
|
||||
struct cdata *cdata;
|
||||
#endif
|
||||
// central cell
|
||||
cell *c7;
|
||||
// associated generator of alternate structure, for Camelot and horocycles
|
||||
heptagon *alt;
|
||||
// functions
|
||||
heptagon*& modmove(int i) { return move[fixrot(i)]; }
|
||||
unsigned char& gspin(int i) { return spin[fixrot(i)]; }
|
||||
unsigned char gspin(int i) { return spin(fixrot(i)); }
|
||||
};
|
||||
|
||||
// the automaton is used to generate each heptagon in an unique way
|
||||
|
@ -54,15 +72,32 @@ struct heptagon {
|
|||
// and sometimes in direction 5
|
||||
|
||||
hstate transition(hstate s, int dir) {
|
||||
if(s == hsOrigin) return hsA;
|
||||
if(s == hsA && dir >= 3 && dir <= 4) return hsA;
|
||||
if(s == hsA && dir == 5) return hsB;
|
||||
if(s == hsB && dir == 4) return hsB;
|
||||
if(s == hsB && dir == 3) return hsA;
|
||||
if(sphere) {
|
||||
if(S7 == 4) {
|
||||
if(s == hsOrigin) return dir == 0 ? hsB0 : hsB1;
|
||||
}
|
||||
if(S7 == 3) {
|
||||
if(s == hsOrigin) return hsB1;
|
||||
}
|
||||
if(s == hsOrigin) return dir == 0 ? hsA0 : hsA1;
|
||||
if(s == hsA0 && dir == 2) return hsB0;
|
||||
if(s == hsA1 && dir == 2) return hsB1;
|
||||
if(s == hsB0 && dir == S7-2) return hsC;
|
||||
return hsError;
|
||||
}
|
||||
else {
|
||||
if(s == hsOrigin) return hsA;
|
||||
if(s == hsA && dir >= 3 && dir <= 4) return hsA;
|
||||
if(s == hsA && dir == 5) return hsB;
|
||||
if(s == hsB && dir == 4) return hsB;
|
||||
if(s == hsB && dir == 3) return hsA;
|
||||
}
|
||||
return hsError;
|
||||
}
|
||||
|
||||
heptagon origin;
|
||||
heptagon dodecahedron[12];
|
||||
#define origin (dodecahedron[0])
|
||||
|
||||
vector<heptagon*> allAlts;
|
||||
|
||||
// create h->move[d] if not created yet
|
||||
|
@ -74,16 +109,16 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0) {
|
|||
h->alt = NULL;
|
||||
h->s = s;
|
||||
for(int i=0; i<7; i++) h->move[i] = NULL;
|
||||
h->move[pard] = parent; h->spin[pard] = d;
|
||||
parent->move[d] = h; parent->spin[d] = pard;
|
||||
h->spintable = 0;
|
||||
h->move[pard] = parent; tsetspin(h->spintable, pard, d);
|
||||
parent->move[d] = h; tsetspin(parent->spintable, d, pard);
|
||||
if(parent->c7) {
|
||||
h->c7 = newCell(7, h);
|
||||
h->emeraldval = emerald_heptagon(parent->emeraldval, d);
|
||||
h->zebraval = zebra_heptagon(parent->zebraval, d);
|
||||
#ifdef CDATA
|
||||
h->fieldval = fp43.connections[fieldpattern::btspin(parent->fieldval, d)];
|
||||
h->rval0 = h->rval1 = 0; h->cdata = NULL;
|
||||
#endif
|
||||
if(parent == &origin)
|
||||
if(parent == &origin || parent == origin.alt)
|
||||
h->fiftyval = fiftytable[0][d];
|
||||
else
|
||||
h->fiftyval = nextfiftyval(parent->fiftyval, parent->move[0]->fiftyval, d);
|
||||
|
@ -98,10 +133,10 @@ heptagon *buildHeptagon(heptagon *parent, int d, hstate s, int pard = 0) {
|
|||
if(pard == 0) {
|
||||
if(purehepta) h->distance = parent->distance + 1;
|
||||
else if(parent->s == hsOrigin) h->distance = 2;
|
||||
else if(h->spin[0] == 5)
|
||||
else if(h->spin(0) == 5)
|
||||
h->distance = parent->distance + 1;
|
||||
else if(h->spin[0] == 4 && h->move[0]->s == hsB)
|
||||
h->distance = createStep(h->move[0], (h->spin[0]+2)%7)->distance + 3;
|
||||
else if(h->spin(0) == 4 && h->move[0]->s == hsB)
|
||||
h->distance = createStep(h->move[0], (h->spin(0)+2)%7)->distance + 3;
|
||||
else h->distance = parent->distance + 2;
|
||||
}
|
||||
else h->distance = parent->distance - (purehepta?1:2);
|
||||
|
@ -112,9 +147,9 @@ void addSpin(heptagon *h, int d, heptagon *from, int rot, int spin) {
|
|||
rot = fixrot(rot);
|
||||
createStep(from, rot);
|
||||
h->move[d] = from->move[rot];
|
||||
h->spin[d] = fixrot(from->spin[rot] + spin);
|
||||
h->move[d]->move[fixrot(from->spin[rot] + spin)] = h;
|
||||
h->move[d]->spin[fixrot(from->spin[rot] + spin)] = d;
|
||||
h->setspin(d, fixrot(from->spin(rot) + spin));
|
||||
h->move[d]->move[fixrot(from->spin(rot) + spin)] = h;
|
||||
h->move[d]->setspin(fixrot(from->spin(rot) + spin), d);
|
||||
//generateEmeraldval(h->move[d]); generateEmeraldval(h);
|
||||
}
|
||||
|
||||
|
@ -122,7 +157,7 @@ extern int hrand(int);
|
|||
|
||||
heptagon *createStep(heptagon *h, int d) {
|
||||
d = fixrot(d);
|
||||
if(h->s != hsOrigin && !h->move[0]) {
|
||||
if(!h->move[0] && h->s != hsOrigin) {
|
||||
buildHeptagon(h, 0, hsA, 3 + hrand(2));
|
||||
}
|
||||
if(h->move[d]) return h->move[d];
|
||||
|
@ -130,18 +165,18 @@ heptagon *createStep(heptagon *h, int d) {
|
|||
buildHeptagon(h, d, hsA);
|
||||
}
|
||||
else if(d == 1) {
|
||||
addSpin(h, d, h->move[0], h->spin[0]-1, -1);
|
||||
addSpin(h, d, h->move[0], h->spin(0)-1, -1);
|
||||
}
|
||||
else if(d == 6) {
|
||||
addSpin(h, d, h->move[0], h->spin[0]+1, +1);
|
||||
addSpin(h, d, h->move[0], h->spin(0)+1, +1);
|
||||
}
|
||||
else if(d == 2) {
|
||||
createStep(h->move[0], h->spin[0]-1);
|
||||
addSpin(h, d, h->move[0]->modmove(h->spin[0]-1), 5 + h->move[0]->gspin(h->spin[0]-1), -1);
|
||||
createStep(h->move[0], h->spin(0)-1);
|
||||
addSpin(h, d, h->move[0]->modmove(h->spin(0)-1), 5 + h->move[0]->gspin(h->spin(0)-1), -1);
|
||||
}
|
||||
else if(d == 5 && h->s == hsB) {
|
||||
createStep(h->move[0], h->spin[0]+1);
|
||||
addSpin(h, d, h->move[0]->modmove(h->spin[0]+1), 2 + h->move[0]->gspin(h->spin[0]+1), +1);
|
||||
createStep(h->move[0], h->spin(0)+1);
|
||||
addSpin(h, d, h->move[0]->modmove(h->spin(0)+1), 2 + h->move[0]->gspin(h->spin(0)+1), +1);
|
||||
}
|
||||
else
|
||||
buildHeptagon(h, d, (d == 5 || (h->s == hsB && d == 4)) ? hsB : hsA);
|
||||
|
@ -153,20 +188,24 @@ heptagon *createStep(heptagon *h, int d) {
|
|||
struct heptspin {
|
||||
heptagon *h;
|
||||
int spin;
|
||||
bool mirrored;
|
||||
heptspin() { mirrored = false; }
|
||||
};
|
||||
|
||||
heptspin hsstep(const heptspin &hs, int spin) {
|
||||
createStep(hs.h, hs.spin);
|
||||
heptspin res;
|
||||
res.h = hs.h->move[hs.spin];
|
||||
res.spin = fixrot(hs.h->spin[hs.spin] + spin);
|
||||
res.mirrored = hs.mirrored ^ hs.h->mirror(hs.spin);
|
||||
res.spin = fixrot(hs.h->spin(hs.spin) + (MIRR(res)?-spin:spin));
|
||||
return res;
|
||||
}
|
||||
|
||||
heptspin hsspin(const heptspin &hs, int val) {
|
||||
heptspin res;
|
||||
res.h = hs.h;
|
||||
res.spin = fixrot(hs.spin + val);
|
||||
res.spin = fixrot(hs.spin + (MIRR(hs)?-val:val));
|
||||
res.mirrored = hs.mirrored;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -174,7 +213,7 @@ heptspin hsspin(const heptspin &hs, int val) {
|
|||
void backtrace(heptagon *pos) {
|
||||
if(pos == &origin) return;
|
||||
backtrace(pos->move[0]);
|
||||
printf(" %d", pos->spin[0]);
|
||||
printf(" %d", pos->spin(0));
|
||||
}
|
||||
|
||||
void hsshow(const heptspin& t) {
|
||||
|
|
582
hyper.cpp
582
hyper.cpp
|
@ -15,46 +15,17 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifdef LOCAL
|
||||
#define CDATA
|
||||
#endif
|
||||
|
||||
#define VER "8.3j"
|
||||
#define VERNUM 8310
|
||||
#define VERNUM_HEX 0x8310
|
||||
|
||||
#define ISANDROID 0
|
||||
#define ISMOBILE 0
|
||||
#define ISIOS 0
|
||||
#define USE_SDL
|
||||
#define USE_COMMANDLINE
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#ifndef MAC
|
||||
#undef main
|
||||
#ifdef STEAM
|
||||
#define NOLICENSE
|
||||
#endif
|
||||
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
FILE *debugfile;
|
||||
int debugflags;
|
||||
|
||||
const char *scorefile = "hyperrogue.log";
|
||||
const char *conffile = "hyperrogue.ini";
|
||||
|
||||
string levelfile = "hyperrogue.lev";
|
||||
string picfile = "hyperrogue.pic";
|
||||
|
||||
const char *loadlevel = NULL;
|
||||
const char *musicfile = "";
|
||||
#include "init.cpp"
|
||||
|
||||
#ifdef LINUX
|
||||
#include <sys/resource.h>
|
||||
|
@ -77,58 +48,29 @@ void moreStack() {
|
|||
}
|
||||
#endif
|
||||
|
||||
string s0;
|
||||
void addMessage(string s, char spamtype = 0);
|
||||
eLand readland(const char *s) {
|
||||
string ss = s;
|
||||
if(ss == "II") return laCrossroads2;
|
||||
if(ss == "III") return laCrossroads3;
|
||||
if(ss == "IV") return laCrossroads4;
|
||||
if(ss == "V") return laCrossroads5;
|
||||
for(int l=0; l<landtypes; l++) if(strstr(linf[l].name, s) != NULL) {
|
||||
return eLand(l);
|
||||
break;
|
||||
}
|
||||
return laNone;
|
||||
}
|
||||
|
||||
int clWidth, clHeight, clFont;
|
||||
string commandline;
|
||||
|
||||
#include "hyperpoint.cpp"
|
||||
#include "patterns.cpp"
|
||||
#include "heptagon.cpp"
|
||||
#include "classes.cpp"
|
||||
#include "language.cpp"
|
||||
|
||||
#ifdef STEAM
|
||||
#define NOLICENSE
|
||||
#endif
|
||||
|
||||
#include "hyper.h"
|
||||
|
||||
#include "cell.cpp"
|
||||
|
||||
#include "flags.cpp"
|
||||
#include "yendor.cpp"
|
||||
#include "complex.cpp"
|
||||
#include "game.cpp"
|
||||
#include "landgen.cpp"
|
||||
#include "orbs.cpp"
|
||||
#include "system.cpp"
|
||||
|
||||
// #include "patterngen.cpp"
|
||||
|
||||
#include "geometry.cpp"
|
||||
|
||||
#include "polygons.cpp"
|
||||
|
||||
#ifndef MOBILE
|
||||
#include "mapeditor.cpp"
|
||||
#endif
|
||||
|
||||
#include "netgen.cpp"
|
||||
|
||||
#include "graph.cpp"
|
||||
|
||||
#include "achievement.cpp"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
#ifdef LINUX
|
||||
moreStack();
|
||||
#endif
|
||||
eItem readItem(const char *s) {
|
||||
string ss = s;
|
||||
for(int i=0; i<ittypes; i++) if(strstr(iinf[i].name, s) != NULL) {
|
||||
return eItem(i);
|
||||
break;
|
||||
}
|
||||
return itNone;
|
||||
}
|
||||
|
||||
void initializeCLI() {
|
||||
printf("HyperRogue by Zeno Rogue <zeno@attnam.com>, version " VER "\n");
|
||||
|
||||
#ifndef NOLICENSE
|
||||
|
@ -136,208 +78,290 @@ int main(int argc, char **argv) {
|
|||
printf("comes with absolutely no warranty; see COPYING for details\n");
|
||||
#endif
|
||||
|
||||
// printf("cell size = %d\n", int(sizeof(cell)));
|
||||
srand(time(NULL));
|
||||
shrand(time(NULL));
|
||||
|
||||
#ifdef FHS
|
||||
char sbuf[640], cbuf[640];
|
||||
static string sbuf, cbuf;
|
||||
if(getenv("HOME")) {
|
||||
snprintf(sbuf, 640, "%s/.%s", getenv("HOME"), scorefile); scorefile = sbuf;
|
||||
snprintf(cbuf, 640, "%s/.%s", getenv("HOME"), conffile); conffile = cbuf;
|
||||
sbuf = getenv("HOME"); sbuf += "/."; sbuf += scorefile;
|
||||
cbuf = getenv("HOME"); cbuf += "/."; cbuf += conffile;
|
||||
scorefile = sbuf.c_str();
|
||||
conffile = cbuf.c_str();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for(int i=1; i<argc; i++) {
|
||||
if(strcmp(argv[i], "-c") == 0 && i != argc-1) {conffile = argv[i+1]; i++;}
|
||||
else if(strcmp(argv[i], "-s") == 0 && i != argc-1) {scorefile = argv[i+1]; i++;}
|
||||
else if(strcmp(argv[i], "-m") == 0 && i != argc-1) {musicfile = argv[i+1]; i++;}
|
||||
else if(strcmp(argv[i], "-lev") == 0 && i != argc-1) {levelfile = argv[i+1]; i++;}
|
||||
else if(strcmp(argv[i], "-pic") == 0 && i != argc-1) {picfile = argv[i+1]; i++;}
|
||||
else if(strcmp(argv[i], "-load") == 0 && i != argc-1) {loadlevel = argv[i+1]; i++;}
|
||||
// else if(strcmp(argv[i], "-P") == 0 && i != argc-1) {par = atoi(argv[i+1]); i++;}
|
||||
else if(strcmp(argv[i], "-W") == 0 && i != argc-1) {
|
||||
for(int l=0; l<landtypes; l++) if(strstr(linf[l].name, argv[i+1]) != NULL) {
|
||||
firstland = euclidland = eLand(l);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else if(strcmp(argv[i], "-L") == 0) {
|
||||
printf("Treasures:\n");
|
||||
for(int i=1; i<ittypes; i++)
|
||||
if(itemclass(eItem(i)) == IC_TREASURE)
|
||||
printf(" %s\n", iinf[i].name);
|
||||
printf("\n");
|
||||
printf("Orbs:\n");
|
||||
for(int i=1; i<ittypes; i++)
|
||||
if(itemclass(eItem(i)) == IC_ORB)
|
||||
printf(" %s\n", iinf[i].name);
|
||||
printf("\n");
|
||||
printf("Other items:\n");
|
||||
for(int i=1; i<ittypes; i++)
|
||||
if(itemclass(eItem(i)) == IC_OTHER)
|
||||
printf(" %s\n", iinf[i].name);
|
||||
printf("\n");
|
||||
printf("Monsters:\n");
|
||||
for(int i=1; i<motypes; i++)
|
||||
printf(" %s\n", minf[i].name);
|
||||
printf("\n");
|
||||
printf("Lands:\n");
|
||||
for(int i=1; i<landtypes; i++)
|
||||
printf(" %s\n", linf[i].name);
|
||||
printf("\n");
|
||||
printf("Walls:\n");
|
||||
for(int i=0; i<walltypes; i++)
|
||||
printf(" %s\n", winf[i].name);
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
else if(strcmp(argv[i], "-f") == 0) { commandline += "f"; }
|
||||
else if(strcmp(argv[i], "-w") == 0) { commandline += "w"; }
|
||||
else if(strcmp(argv[i], "-e") == 0) { commandline += "e"; }
|
||||
else if(strcmp(argv[i], "-a") == 0) { commandline += "a"; }
|
||||
else if(strcmp(argv[i], "-p") == 0) { commandline += "p"; }
|
||||
else if(strcmp(argv[i], "-7") == 0) { commandline += "7"; }
|
||||
else if(strcmp(argv[i], "-C") == 0) { commandline += "C"; }
|
||||
else if(strcmp(argv[i], "-o") == 0) { commandline += "o"; }
|
||||
else if(strcmp(argv[i], "-o0") == 0) { commandline += char(200); }
|
||||
else if(strcmp(argv[i], "-o1") == 0) { commandline += char(201); }
|
||||
else if(strcmp(argv[i], "-E") == 0) { commandline += "E"; }
|
||||
else if(strcmp(argv[i], "-S") == 0) { commandline += "S"; }
|
||||
else if(strcmp(argv[i], "-H") == 0) { commandline += "H"; }
|
||||
else if(strcmp(argv[i], "-P1") == 0) { commandline += "P1"; }
|
||||
else if(strcmp(argv[i], "-P2") == 0) { commandline += "P2"; }
|
||||
else if(strcmp(argv[i], "-P3") == 0) { commandline += "P3"; }
|
||||
else if(strcmp(argv[i], "-P4") == 0) { commandline += "P4"; }
|
||||
else if(strcmp(argv[i], "-T") == 0) { commandline += "T"; }
|
||||
else if(strcmp(argv[i], "-R") == 0) { commandline += "R"; }
|
||||
else if(strcmp(argv[i], "-D") == 0) { commandline += "D"; }
|
||||
else if(strcmp(argv[i], "-PM1") == 0) { pmodel = 1; }
|
||||
else if(strcmp(argv[i], "-PM2") == 0) { pmodel = 2; }
|
||||
else if(strcmp(argv[i], "-offline") == 0) offlineMode = true;
|
||||
else if(strcmp(argv[i], "-debugf") == 0) {
|
||||
debugfile = fopen("hyperrogue-debug.txt", "w");
|
||||
debugflags = atoi(argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
else if(strcmp(argv[i], "-debuge") == 0) {
|
||||
debugfile = stderr;
|
||||
debugflags = atoi(argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
#ifdef LOCAL
|
||||
else if(strcmp(argv[i], "-auto") == 0) doAutoplay = true;
|
||||
int arg::readCommon() {
|
||||
if(argis("-c")) { PHASE(1); shift(); conffile = args(); }
|
||||
else if(argis("-s")) { PHASE(1); shift(); scorefile = args(); }
|
||||
else if(argis("-m")) { PHASE(1); shift(); musicfile = args(); }
|
||||
else if(argis("-se")) { PHASE(1); shift(); wheresounds = args(); }
|
||||
#ifndef NOEDIT
|
||||
else if(argis("-lev")) { shift(); levelfile = args(); }
|
||||
else if(argis("-pic")) { shift(); picfile = args(); }
|
||||
else if(argis("-load")) { PHASE(3); shift(); mapstream::loadMap(loadlevel); }
|
||||
#endif
|
||||
else if(strcmp(argv[i], "-ch") == 0) { autocheat = true; }
|
||||
else if(strcmp(argv[i], "-Y") == 0) {
|
||||
yendor::on = true;
|
||||
yendor::challenge = atoi(argv[i+1]);
|
||||
i++;
|
||||
}
|
||||
else if(strcmp(argv[i], "-r") == 0) {
|
||||
i++;
|
||||
sscanf(argv[i], "%dx%dx%d", &clWidth, &clHeight, &clFont);
|
||||
}
|
||||
else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
|
||||
printf("HyperRogue version " VER "\n");
|
||||
exit(0);
|
||||
}
|
||||
else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
|
||||
printf("Press F1 while playing to get ingame options.\n\n");
|
||||
printf("HyperRogue accepts the following command line options:\n");
|
||||
printf(" -c FILE - use the specified configuration file\n");
|
||||
printf(" -s FILE - use the specified highscore file\n");
|
||||
printf(" -m FILE - use the specified soundtrack (music)\n");
|
||||
printf(" -lev FILE - use the specified filename for the map editor (without loading)\n");
|
||||
printf(" -load FILE - use the specified filename for the map editor\n");
|
||||
printf(" --version, -v - show the version number\n");
|
||||
printf(" --help, -h - show the commandline options\n");
|
||||
printf(" -f, -w - start in the fullscreen or windowed mode\n");
|
||||
printf(" -e, -a, -p - start in the Escher, ASCII, or Plain mode\n");
|
||||
printf(" -r WxHxF - use the given resolution and font size\n");
|
||||
printf(" -o - switch the OpenGL mode\n");
|
||||
printf(" -o0 - switch the OpenGL mode off\n");
|
||||
printf(" -o1 - switch the OpenGL mode on\n");
|
||||
printf(" -W LAND - start in the given land (cheat)\n");
|
||||
printf(" -ch - auto-enable cheat mode\n");
|
||||
printf(" -E - switch Euclidean\n");
|
||||
printf(" -S - switch Shmup\n");
|
||||
printf(" -Pn - switch Shmup number of players (n=1..4)\n");
|
||||
printf(" -H - switch Hardcore\n");
|
||||
printf(" -T - switch Tactical\n");
|
||||
printf(" -7 - switch heptagonal mode\n");
|
||||
printf(" -C - switch Chaos mode\n");
|
||||
printf(" -R - switch Random Pattern\n");
|
||||
printf(" -Y id - switch Yendor, level id\n");
|
||||
printf(" -D - disable all the special game modes\n");
|
||||
printf(" -L - list of features\n");
|
||||
printf(" -debugf 7 - output debugging information to hyperrogue-debug.txt\n");
|
||||
printf(" -debuge 7 - output debugging information to stderr\n");
|
||||
printf(" -offline - don't connect to Steam (for Steam versions)\n");
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
printf("Unknown option: %s\n", argv[i]);
|
||||
else if(argis("-canvas")) {
|
||||
firstland = euclidland = laCanvas;
|
||||
shift();
|
||||
if(args()[1] == 0) mapeditor::whichCanvas = args()[0];
|
||||
else mapeditor::canvasback = strtol(args(), NULL, 16);
|
||||
}
|
||||
else if(argis("-back")) {
|
||||
shift(); backcolor = strtol(args(), NULL, 16);
|
||||
}
|
||||
else if(argis("-W2")) {
|
||||
shift(); cheatdest = readland(args()); autocheat = true;
|
||||
}
|
||||
else if(argis("-W")) {
|
||||
shift(); firstland = euclidland = readland(args());
|
||||
}
|
||||
else if(argis("-I")) {
|
||||
PHASE(3) cheater++; timerghost = false;
|
||||
shift(); eItem i = readItem(args());
|
||||
shift(); items[i] = argi();
|
||||
}
|
||||
else if(argis("-L")) {
|
||||
printf("Treasures:\n");
|
||||
for(int i=1; i<ittypes; i++)
|
||||
if(itemclass(eItem(i)) == IC_TREASURE)
|
||||
printf(" %s\n", iinf[i].name);
|
||||
printf("\n");
|
||||
printf("Orbs:\n");
|
||||
for(int i=1; i<ittypes; i++)
|
||||
if(itemclass(eItem(i)) == IC_ORB)
|
||||
printf(" %s\n", iinf[i].name);
|
||||
printf("\n");
|
||||
printf("Other items:\n");
|
||||
for(int i=1; i<ittypes; i++)
|
||||
if(itemclass(eItem(i)) == IC_OTHER)
|
||||
printf(" %s\n", iinf[i].name);
|
||||
printf("\n");
|
||||
printf("Monsters:\n");
|
||||
for(int i=1; i<motypes; i++)
|
||||
printf(" %s\n", minf[i].name);
|
||||
printf("\n");
|
||||
printf("Lands:\n");
|
||||
for(int i=1; i<landtypes; i++)
|
||||
printf(" %s\n", linf[i].name);
|
||||
printf("\n");
|
||||
printf("Walls:\n");
|
||||
for(int i=0; i<walltypes; i++)
|
||||
printf(" %s\n", winf[i].name);
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
else if(argis("-wm")) { PHASE(2); vid.wallmode = argi(); }
|
||||
else if(argis("-mm")) { PHASE(2); vid.monmode = argi(); }
|
||||
|
||||
#define TOGGLE(x, param) \
|
||||
else if(args()[0] == '-' && args()[1] == x && !args()[2]) { PHASE(2); param = !param; } \
|
||||
else if(args()[0] == '-' && args()[1] == x && args()[2] == '1') { PHASE(2); param = true; } \
|
||||
else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { PHASE(2); param = false; }
|
||||
|
||||
TOGGLE('o', vid.usingGL)
|
||||
TOGGLE('C', chaosmode)
|
||||
TOGGLE('7', purehepta)
|
||||
TOGGLE('f', vid.full)
|
||||
TOGGLE('T', tactic::on)
|
||||
TOGGLE('S', shmup::on)
|
||||
TOGGLE('H', hardcore)
|
||||
TOGGLE('R', randomPatternsMode)
|
||||
|
||||
else if(argis("-geo")) { PHASE(2); shift(); geometry = targetgeometry = (eGeometry) argi(); }
|
||||
else if(argis("-qs")) {
|
||||
autocheat = true;
|
||||
shift(); fp43.qpaths.push_back(args());
|
||||
}
|
||||
else if(argis("-fix")) {
|
||||
fixseed = true; autocheat = true;
|
||||
}
|
||||
else if(argis("-qpar")) {
|
||||
int p;
|
||||
shift(); sscanf(args(), "%d,%d,%d",
|
||||
&p, "ientspace::rvadd, "ientspace::rvdir
|
||||
);
|
||||
autocheat = true;
|
||||
fp43.init(p);
|
||||
}
|
||||
else if(argis("-cs")) {
|
||||
shift();
|
||||
fieldpattern::matrix M = fp43.strtomatrix(args());
|
||||
fieldpattern::subpathid = fp43.matcode[M];
|
||||
fieldpattern::subpathorder = fp43.order(M);
|
||||
autocheat = true;
|
||||
}
|
||||
else if(argis("-csp")) {
|
||||
autocheat = true;
|
||||
fp43.findsubpath();
|
||||
}
|
||||
else if(argis("-fi")) {
|
||||
fieldpattern::info();
|
||||
exit(0);
|
||||
}
|
||||
else if(argis("-P")) {
|
||||
PHASE(2); shift();
|
||||
vid.scfg.players = argi();
|
||||
}
|
||||
else if(argis("-PM")) {
|
||||
PHASE(2); shift(); pmodel = eModel(argi());
|
||||
}
|
||||
else if(argis("-offline")) offlineMode = true;
|
||||
else if(argis("-debugf")) {
|
||||
debugfile = fopen("hyperrogue-debug.txt", "w");
|
||||
shift(); debugflags = argi();
|
||||
}
|
||||
else if(argis("-debuge")) {
|
||||
debugfile = stderr;
|
||||
shift(); debugflags = argi();
|
||||
}
|
||||
else if(argis("-ch")) { autocheat = true; }
|
||||
else if(argis("-zoom") && curphase == 2) {
|
||||
PHASE(2); shift(); vid.scale = argf();
|
||||
}
|
||||
else if(argis("-zoom") && curphase == 3) {
|
||||
PHASE(3); shift(); vid.scale = argf();
|
||||
}
|
||||
else if(argis("-Y")) {
|
||||
yendor::on = true;
|
||||
shift(); yendor::challenge = argi();
|
||||
}
|
||||
else if(argis("-r")) {
|
||||
PHASE(2);
|
||||
shift();
|
||||
int clWidth=0, clHeight=0, clFont=0;
|
||||
sscanf(args(), "%dx%dx%d", &clWidth, &clHeight, &clFont);
|
||||
if(clWidth) vid.xres = clWidth;
|
||||
if(clHeight) vid.yres = clHeight;
|
||||
if(clFont) vid.fsize = clFont;
|
||||
}
|
||||
else if(argis("--version") || argis("-v")) {
|
||||
printf("HyperRogue version " VER "\n");
|
||||
exit(0);
|
||||
}
|
||||
else if(argis("--run")) {
|
||||
PHASE(3); mainloop(); quitmainloop = false;
|
||||
}
|
||||
else if(argis("--draw")) {
|
||||
PHASE(3); drawscreen();
|
||||
}
|
||||
else if(argis("--exit")) {
|
||||
PHASE(3); printf("Success.\n");
|
||||
exit(0);
|
||||
}
|
||||
else if(argis("-gencells")) {
|
||||
PHASE(3); shift();
|
||||
printf("Generating %d cells...\n", argi());
|
||||
celllister cl(cwt.c, 50, argi(), NULL);
|
||||
printf("Cells generated: %d\n", size(cl.lst));
|
||||
for(int i=0; i<size(cl.lst); i++)
|
||||
setdist(cl.lst[i], 7, NULL);
|
||||
}
|
||||
else if(argis("-sr")) {
|
||||
if(curphase == 1) PHASE(2);
|
||||
shift(); sightrange = argi();
|
||||
}
|
||||
else if(argis("-pngshot")) {
|
||||
PHASE(3); shift();
|
||||
printf("saving PNG screenshot to %s\n", args());
|
||||
saveHighQualityShot(args());
|
||||
}
|
||||
else if(argis("-svgsize")) {
|
||||
shift(); sscanf(args(), "%d/%d", &svg::svgsize, &svg::divby);
|
||||
}
|
||||
else if(argis("-pngsize")) {
|
||||
shift(); sscanf(args(), "%d", &pngres);
|
||||
}
|
||||
else if(argis("-svggamma")) {
|
||||
shift(); svg::gamma = argf();
|
||||
}
|
||||
else if(argis("-svgshot")) {
|
||||
PHASE(3); shift();
|
||||
printf("saving SVG screenshot to %s\n", args());
|
||||
svg::render(args());
|
||||
}
|
||||
else if(argis("--help") || argis("-h")) {
|
||||
printf("Press F1 while playing to get ingame options.\n\n");
|
||||
printf("HyperRogue accepts the following command line options:\n");
|
||||
printf(" -c FILE - use the specified configuration file\n");
|
||||
printf(" -s FILE - use the specified highscore file\n");
|
||||
printf(" -m FILE - use the specified soundtrack (music)\n");
|
||||
printf(" -se DIR - the directory containing sound effects\n");
|
||||
printf(" -lev FILE - use the specified filename for the map editor (without loading)\n");
|
||||
printf(" -load FILE - use the specified filename for the map editor\n");
|
||||
printf(" -canvas COLOR - set background color or pattern code for the canvas\n");
|
||||
printf(" --version, -v - show the version number\n");
|
||||
printf(" --help, -h - show the commandline options\n");
|
||||
printf(" -f* - toggle fullscreen mode\n");
|
||||
printf(" -wm n, -mm n - start in the given wallmode or monmode\n");
|
||||
printf(" -r WxHxF - use the given resolution and font size\n");
|
||||
printf(" -o* - toggle the OpenGL mode\n");
|
||||
printf(" -W LAND - start in the given land (cheat)\n");
|
||||
printf(" -W2 LAND - make the given land easy to find (also turns on autocheat)\n");
|
||||
printf(" -ch - auto-enable cheat mode\n");
|
||||
printf(" -geo n - switch geometry (1=Euclidean, 2=spherical, 3=elliptic, 4/5=quotient)\n");
|
||||
printf(" -qs <desc> - fieldpattern: quotient by the given <desc> (must be followed by qpar)\n");
|
||||
printf(" -qpar <prime> - fieldpattern: use the given prime instead of 43\n");
|
||||
printf(" -cs <desc> - fieldpattern: set subpath to the given <desc> (cannot be followed by qpar)\n");
|
||||
printf(" -csp - fieldpattern: find the subpath of order <prime> (cannot be followed by qpar)\n");
|
||||
printf(" -S* - toggle Shmup\n");
|
||||
printf(" -P n - switch Shmup number of players (n=1..7)\n");
|
||||
printf(" -PM - switch the model index\n");
|
||||
printf(" -H* - toggle Hardcore\n");
|
||||
printf(" -T* - toggle Tactical\n");
|
||||
printf(" -7* - toggle heptagonal mode\n");
|
||||
printf(" -C* - toggle Chaos mode\n");
|
||||
printf(" -R* - toggle Random Pattern\n");
|
||||
printf(" -Y id - enable Yendor, level id\n");
|
||||
printf(" -D - disable all the special game modes\n");
|
||||
printf(" -L - list of features\n");
|
||||
printf(" -debugf 7 - output debugging information to hyperrogue-debug.txt\n");
|
||||
printf(" -debuge 7 - output debugging information to stderr\n");
|
||||
printf(" -offline - don't connect to Steam (for Steam versions)\n");
|
||||
printf(" -I ITEM n - start with n of ITEM (activates cheat and disables ghosts)\n");
|
||||
printf(" -fix - fix the seed\n");
|
||||
printf("Toggles: -o0 disables, -o1 enables, -o switches");
|
||||
printf("Not all options are documented, see hyper.cpp");
|
||||
exit(0);
|
||||
}
|
||||
else if(ca::readArg()) ;
|
||||
else return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#ifndef WEB
|
||||
#ifdef LINUX
|
||||
moreStack();
|
||||
#endif
|
||||
arg::init(argc, argv);
|
||||
initializeCLI();
|
||||
#endif
|
||||
initAll();
|
||||
arg::read(3);
|
||||
mainloop();
|
||||
finishAll();
|
||||
profile_info();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_COMMANDLINE
|
||||
namespace arg {
|
||||
int argc; char **argv;
|
||||
|
||||
void read(int phase) {
|
||||
curphase = phase;
|
||||
while(argc) {
|
||||
int r;
|
||||
r = readCommon(); if(r == 2) return; if(r == 0) { lshift(); continue; }
|
||||
#ifdef LOCAL
|
||||
r = readLocal(); if(r == 2) return; if(r == 0) { lshift(); continue; }
|
||||
#endif
|
||||
#ifdef ROGUEVIZ
|
||||
r = rogueviz::readArgs(); if(r == 2) return; if(r == 0) { lshift(); continue; }
|
||||
#endif
|
||||
printf("Unknown option: %s\n", args());
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
achievement_init();
|
||||
|
||||
eLand f = firstland;
|
||||
|
||||
// initlanguage();
|
||||
initgraph();
|
||||
loadsave();
|
||||
precalc();
|
||||
resetGL();
|
||||
initcells();
|
||||
|
||||
#ifdef BUILDZEBRA
|
||||
firstland = laCanvas;
|
||||
shmup::on = false;
|
||||
#endif
|
||||
shmup::safety = safety;
|
||||
initgame();
|
||||
#ifdef BUILDZEBRA
|
||||
zebraPattern();
|
||||
#endif
|
||||
|
||||
if(!shmup::on) {
|
||||
restoreGolems(items[itOrbLife], moGolem); items[itOrbLife] = 0;
|
||||
restoreGolems(items[itOrbFriend], moTameBomberbird); items[itOrbFriend] = 0;
|
||||
restoreGolems(kills[moPrincessMoved], moPrincess, princess::saveHP); kills[moPrincessMoved] = 0;
|
||||
restoreGolems(kills[moPrincessArmedMoved], moPrincessArmed, princess::saveArmedHP); kills[moPrincessArmedMoved] = 0;
|
||||
}
|
||||
|
||||
firstland = f;
|
||||
|
||||
// verifyHell();
|
||||
// exit(1);
|
||||
|
||||
int t1 = SDL_GetTicks();
|
||||
|
||||
// if(switchEuclid) restartGame('e');
|
||||
|
||||
if(loadlevel) mapstream::loadMap(loadlevel);
|
||||
|
||||
#ifdef LOCAL
|
||||
// river();
|
||||
autoplay();
|
||||
#endif
|
||||
mainloop();
|
||||
|
||||
achievement_final(!items[itOrbSafety]);
|
||||
|
||||
saveStats();
|
||||
int msec = SDL_GetTicks() - t1;
|
||||
DEBB(DF_INIT, (debugfile, "frame : %f ms (%f fps)\n", 1.*msec/frames, 1000.*frames/msec));
|
||||
offscreen.clear();
|
||||
clearMemory();
|
||||
cleargraph();
|
||||
|
||||
achievement_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
604
hyper.h
604
hyper.h
|
@ -7,6 +7,9 @@
|
|||
|
||||
#define GL
|
||||
|
||||
#define PSEUDOKEY_WHEELDOWN 2501
|
||||
#define PSEUDOKEY_WHEELUP 2502
|
||||
|
||||
#ifdef NOGFX
|
||||
#undef GFX
|
||||
#endif
|
||||
|
@ -18,9 +21,10 @@
|
|||
// scale the Euclidean
|
||||
#define EUCSCALE 2.3
|
||||
|
||||
// disable this if you have no access to SDL_mixer
|
||||
#ifndef MOBILE
|
||||
#define AUDIO
|
||||
#ifndef NOAUDIO
|
||||
#define SDLAUDIO
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NUMWITCH 7
|
||||
|
@ -29,7 +33,7 @@
|
|||
|
||||
#define LB_YENDOR_CHALLENGE 40
|
||||
#define LB_PURE_TACTICS 41
|
||||
#define NUMLEADER 57
|
||||
#define NUMLEADER 69
|
||||
#define LB_PURE_TACTICS_SHMUP 49
|
||||
#define LB_PURE_TACTICS_COOP 50
|
||||
|
||||
|
@ -75,6 +79,7 @@ void achievement_pump();
|
|||
vector<string> achievementsReceived;
|
||||
|
||||
// game forward declarations
|
||||
typedef int flagtype;
|
||||
|
||||
bool mirrorkill(cell *c);
|
||||
bool isNeighbor(cell *c1, cell *c2);
|
||||
|
@ -82,7 +87,7 @@ void checkTide(cell *c);
|
|||
namespace anticheat { extern bool tampered; }
|
||||
int numplayers();
|
||||
void removeIvy(cell *c);
|
||||
bool cellEdgeUnstable(cell *c);
|
||||
bool cellEdgeUnstable(cell *c, flagtype flags = 0);
|
||||
int coastvalEdge(cell *c);
|
||||
typedef int cellfunction(cell*);
|
||||
int towerval(cell *c, cellfunction* cf = &coastvalEdge);
|
||||
|
@ -94,13 +99,13 @@ 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);
|
||||
void makeEmpty(cell *c);
|
||||
bool makeEmpty(cell *c);
|
||||
bool isCrossroads(eLand l);
|
||||
enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce };
|
||||
enum orbAction { roMouse, roKeyboard, roCheck, roMouseForce, roMultiCheck, roMultiGo };
|
||||
void moveItem (cell *from, cell *to, bool activateYendor);
|
||||
void uncoverMines(cell *c, int lev);
|
||||
void uncoverMines(cell *c, int lev, int dist);
|
||||
bool survivesMine(eMonster m);
|
||||
void killMonster(cell *c);
|
||||
void killMonster(cell *c, eMonster who_killed, flagtype flags = 0);
|
||||
void toggleGates(cell *ct, eWall type, int rad);
|
||||
bool destroyHalfvine(cell *c, eWall newwall = waNone, int tval = 6);
|
||||
void buildCrossroads2(cell *c);
|
||||
|
@ -109,12 +114,12 @@ heptagon *createAlternateMap(cell *c, int rad, hstate firststate, int special=0)
|
|||
void generateAlts(heptagon *h);
|
||||
void setdist(cell *c, int d, cell *from);
|
||||
void checkOnYendorPath();
|
||||
void killThePlayerAt(eMonster m, cell *c, int flags);
|
||||
void killThePlayerAt(eMonster m, cell *c, flagtype flags);
|
||||
bool notDippingFor(eItem i);
|
||||
bool collectItem(cell *c2, bool telekinesis = false);
|
||||
void castLightningBolt(struct cellwalker lig);
|
||||
bool movepcto(int d, int subdir = 1, bool checkonly = false);
|
||||
void stabbingAttack(cell *mf, cell *mt, eMonster who);
|
||||
void stabbingAttack(cell *mf, cell *mt, eMonster who, int bonuskill = 0);
|
||||
bool earthMove(cell *from, int dir);
|
||||
void messageKill(eMonster killer, eMonster victim);
|
||||
void moveMonster(cell *ct, cell *cf);
|
||||
|
@ -122,6 +127,7 @@ int palaceHP();
|
|||
void placeLocalOrbs(cell *c);
|
||||
int elementalKills();
|
||||
bool elementalUnlocked();
|
||||
bool trollUnlocked();
|
||||
bool isMultitile(eMonster m);
|
||||
void checkFreedom(cell *cf);
|
||||
int rosedist(cell *c);
|
||||
|
@ -137,7 +143,16 @@ namespace mirror {
|
|||
|
||||
int neighborId(cell *c1, cell *c2);
|
||||
|
||||
struct movedir { int d; int subdir; };
|
||||
struct movedir {
|
||||
int d; // 0 to 6, or one of the following -- warning: not used consistently
|
||||
#define MD_WAIT (-1)
|
||||
#define MD_DROP (-2)
|
||||
#define MD_UNDECIDED (-3)
|
||||
#define MD_USE_ORB (-4)
|
||||
int subdir; // for normal movement (0-6): turn left or right
|
||||
cell *tgt; // for MD_USE_ORB: target cell
|
||||
};
|
||||
|
||||
inline bool movepcto(const movedir& md) { return movepcto(md.d, md.subdir); }
|
||||
|
||||
void activateActiv(cell *c, bool msg);
|
||||
|
@ -145,19 +160,65 @@ void activateActiv(cell *c, bool msg);
|
|||
// shmup
|
||||
|
||||
struct charstyle {
|
||||
int charid, skincolor, haircolor, dresscolor, swordcolor, dresscolor2;
|
||||
int charid, skincolor, haircolor, dresscolor, swordcolor, dresscolor2, uicolor;
|
||||
};
|
||||
|
||||
string csname(charstyle& cs);
|
||||
void initcs(charstyle& cs);
|
||||
void savecs(FILE *f, charstyle& cs);
|
||||
void loadcs(FILE *f, charstyle& cs);
|
||||
void savecs(FILE *f, charstyle& cs, int vernum);
|
||||
void loadcs(FILE *f, charstyle& cs, int vernum);
|
||||
|
||||
#define MAXPLAYER 7
|
||||
#define MAXJOY 8
|
||||
|
||||
#define MAXBUTTON 64
|
||||
#define MAXAXE 16
|
||||
#define MAXHAT 4
|
||||
|
||||
namespace multi {
|
||||
|
||||
void recall();
|
||||
extern cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER];
|
||||
extern int players;
|
||||
extern cellwalker player[MAXPLAYER];
|
||||
extern bool flipped[MAXPLAYER];
|
||||
cell *mplayerpos(int i);
|
||||
|
||||
extern vector<int> revive_queue; // queue for revival
|
||||
|
||||
extern movedir whereto[MAXPLAYER]; // player's target cell
|
||||
|
||||
extern int cpid; // player id -- an extra parameter for player-related functions
|
||||
extern int cpid_edit; // cpid currently being edited
|
||||
|
||||
// treasure collection, kill, and death statistics
|
||||
extern int treasures[MAXPLAYER], kills[MAXPLAYER], deaths[MAXPLAYER];
|
||||
|
||||
struct config {
|
||||
int players;
|
||||
int subconfig;
|
||||
int setwhat;
|
||||
char keyaction[512];
|
||||
char joyaction[MAXJOY][MAXBUTTON];
|
||||
char axeaction[MAXJOY][MAXAXE];
|
||||
char hataction[MAXJOY][MAXHAT][4];
|
||||
int deadzoneval[MAXJOY][MAXAXE];
|
||||
};
|
||||
|
||||
charstyle scs[MAXPLAYER];
|
||||
|
||||
bool playerActive(int p);
|
||||
int activePlayers();
|
||||
cell *multiPlayerTarget(int i);
|
||||
void checklastmove();
|
||||
void leaveGame(int i);
|
||||
}
|
||||
|
||||
namespace shmup {
|
||||
void recall();
|
||||
extern bool on;
|
||||
extern bool safety;
|
||||
extern int curtime;
|
||||
extern int players, cpid;
|
||||
void clearMemory();
|
||||
void init();
|
||||
void teleported();
|
||||
|
@ -175,22 +236,8 @@ namespace shmup {
|
|||
cell *playerpos(int i);
|
||||
|
||||
bool playerInBoat(int i);
|
||||
|
||||
#define MAXBUTTON 64
|
||||
#define MAXAXE 16
|
||||
#define MAXHAT 4
|
||||
|
||||
struct config {
|
||||
int players;
|
||||
int subconfig;
|
||||
int setwhat;
|
||||
char keyaction[512];
|
||||
char joyaction[8][MAXBUTTON];
|
||||
char axeaction[8][MAXAXE];
|
||||
char hataction[8][MAXHAT][4];
|
||||
};
|
||||
|
||||
charstyle scs[4];
|
||||
void destroyBoats(cell *c);
|
||||
bool boatAt(cell *c);
|
||||
}
|
||||
|
||||
// graph
|
||||
|
@ -206,6 +253,10 @@ void cleargraphmemory();
|
|||
|
||||
void drawFlash(cell* c);
|
||||
void drawBigFlash(cell* c);
|
||||
void drawParticle(cell *c, int col, int maxspeed = 100);
|
||||
void drawParticles(cell *c, int col, int qty, int maxspeed = 100);
|
||||
void drawFireParticles(cell *c, int qty, int maxspeed = 100);
|
||||
int firecolor(int phase);
|
||||
|
||||
void drawLightning();
|
||||
void drawSafety();
|
||||
|
@ -214,8 +265,6 @@ void movepckeydir(int);
|
|||
|
||||
void centerpc(ld aspd);
|
||||
|
||||
void displayStatHelp(int y, string name);
|
||||
void displayStat(int y, const string& name, const string& val, char mkey);
|
||||
void displayButton(int x, int y, const string& name, int key, int align, int rad = 0);
|
||||
void displayColorButton(int x, int y, const string& name, int key, int align, int rad, int color, int color2 = 0);
|
||||
inline string ONOFF(bool b) { return XLAT(b ? "ON" : "OFF"); }
|
||||
|
@ -223,17 +272,15 @@ int darkened(int c);
|
|||
extern int getcstat;
|
||||
bool displaychr(int x, int y, int shift, int size, char chr, int col);
|
||||
bool displayfr(int x, int y, int b, int size, const string &s, int color, int align);
|
||||
void saveHighQualityShot();
|
||||
void saveHighQualityShot(const char *fname = NULL);
|
||||
|
||||
bool outofmap(hyperpoint h);
|
||||
void getcoord(const hyperpoint& H, int& x, int& y, int &shift);
|
||||
void drawline(const hyperpoint& H1, int x1, int y1, int s1, const hyperpoint& H2, int x2, int y2, int col);
|
||||
void drawline(const hyperpoint& H1, const hyperpoint& H2, int col);
|
||||
void applymodel(hyperpoint H, hyperpoint& Hscr);
|
||||
void drawCircle(int x, int y, int size, int color);
|
||||
void fixcolor(int& col);
|
||||
int displaydir(cell *c, int d);
|
||||
hyperpoint gethyper(ld x, ld y);
|
||||
void resetview(); extern cell *lcenterover; extern heptspin viewctr;
|
||||
void resetview(); extern heptspin viewctr; extern cell *centerover;
|
||||
#ifndef MOBILE
|
||||
int& qpixel(SDL_Surface *surf, int x, int y);
|
||||
#endif
|
||||
|
@ -245,31 +292,30 @@ extern int darken;
|
|||
void setvideomode();
|
||||
void calcparam();
|
||||
|
||||
string ifMousing(string key, string s);
|
||||
|
||||
#ifndef NOCONFIG
|
||||
void saveConfig();
|
||||
#endif
|
||||
|
||||
extern hyperpoint mouseh;
|
||||
|
||||
extern int webdisplay;
|
||||
|
||||
extern bool GL_initialized;
|
||||
extern hyperpoint ccenter;
|
||||
extern ld crad;
|
||||
|
||||
extern bool mousepressed, anyshiftclick;
|
||||
extern string help;
|
||||
|
||||
extern int lalpha;
|
||||
|
||||
struct videopar {
|
||||
ld scale, eye, alpha, aspeed;
|
||||
ld scale, eye, alpha, sspeed, mspeed, yshift, camera_angle;
|
||||
ld ballangle, ballproj;
|
||||
int mobilecompasssize;
|
||||
|
||||
bool full;
|
||||
bool goteyes; // for rendering
|
||||
bool goteyes2; // for choosing colors
|
||||
bool quick;
|
||||
bool darkhepta;
|
||||
bool shifttarget;
|
||||
int shifttarget;
|
||||
|
||||
int xres, yres, framelimit;
|
||||
|
||||
|
@ -280,6 +326,9 @@ struct videopar {
|
|||
int radius;
|
||||
ld alphax, beta;
|
||||
|
||||
bool grid;
|
||||
int particles;
|
||||
|
||||
int fsize;
|
||||
int flashtime;
|
||||
|
||||
|
@ -292,7 +341,7 @@ struct videopar {
|
|||
bool usingAA;
|
||||
|
||||
int joyvalue, joyvalue2, joypanthreshold;
|
||||
float joypanspeed;
|
||||
ld joypanspeed;
|
||||
|
||||
charstyle cs;
|
||||
|
||||
|
@ -301,9 +350,10 @@ struct videopar {
|
|||
|
||||
int killreduction, itemreduction, portreduction;
|
||||
|
||||
shmup::config scfg;
|
||||
multi::config scfg;
|
||||
|
||||
bool steamscore;
|
||||
int steamscore;
|
||||
bool drawmousecircle; // draw the circle around the mouse
|
||||
};
|
||||
|
||||
extern videopar vid;
|
||||
|
@ -322,7 +372,10 @@ enum emtype {emNormal, emHelp,
|
|||
emYendor, emTactic, emRugConfig,
|
||||
emConformal,
|
||||
emProgress,
|
||||
emCheatMenu
|
||||
emCheatMenu, emLeader,
|
||||
emJoyConfig,
|
||||
emColor, emNumber,
|
||||
em3D, emRogueviz
|
||||
};
|
||||
|
||||
extern emtype cmode, lastmode;
|
||||
|
@ -338,14 +391,18 @@ extern struct SDL_Surface *s;
|
|||
namespace mapeditor {
|
||||
extern bool drawplayer;
|
||||
extern char whichPattern, whichShape;
|
||||
extern char whichCanvas;
|
||||
extern int displaycodes;
|
||||
int generateCanvas(cell *c);
|
||||
void clearModelCells();
|
||||
void applyModelcell(cell *c);
|
||||
int realpattern(cell *c);
|
||||
int patterndir(cell *c, char w = whichPattern);
|
||||
int subpattern(cell *c);
|
||||
extern cell *drawcell;
|
||||
}
|
||||
|
||||
#ifndef NORUG
|
||||
namespace rug {
|
||||
extern bool rugged;
|
||||
void init();
|
||||
|
@ -353,6 +410,7 @@ namespace rug {
|
|||
void actDraw();
|
||||
void buildVertexInfo(cell *c, transmatrix V);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HASLINEVIEW
|
||||
namespace conformal {
|
||||
|
@ -372,9 +430,8 @@ namespace conformal {
|
|||
|
||||
namespace polygonal {
|
||||
extern int SI;
|
||||
extern double STAR;
|
||||
extern ld STAR;
|
||||
void solve();
|
||||
typedef long double ld;
|
||||
pair<ld, ld> compute(ld x, ld y);
|
||||
}
|
||||
|
||||
|
@ -422,8 +479,9 @@ extern bool localKill(shmup::monster *m);
|
|||
#define P_ROSE (1<<28) // rose smell
|
||||
#define P_CLIMBUP (1<<29) // allow climbing up
|
||||
#define P_CLIMBDOWN (1<<30) // allow climbing down
|
||||
#define P_REPTILE (1<<31) // is reptile
|
||||
|
||||
bool passable(cell *w, cell *from, int flags);
|
||||
bool passable(cell *w, cell *from, flagtype flags);
|
||||
|
||||
bool isElemental(eLand l);
|
||||
int coastval(cell *c, eLand base);
|
||||
|
@ -450,13 +508,15 @@ extern bool safety;
|
|||
|
||||
#define SAGEMELT .1
|
||||
#define TEMPLE_EACH 6
|
||||
#define PT(x, y) (tactic::on ? (y) : (x))
|
||||
#define PT(x, y) ((tactic::on || quotient == 2) ? (y) : (x))
|
||||
#define ROCKSNAKELENGTH 50
|
||||
#define WORMLENGTH 15
|
||||
#define PUREHARDCORE_LEVEL 10
|
||||
#define PRIZEMUL 7
|
||||
|
||||
#define INF 9999
|
||||
#define INFD 20
|
||||
#define PINFD 125
|
||||
#define BARLEV ((ISANDROID||ISIOS||purehepta)?9:10)
|
||||
#define BUGLEV 15
|
||||
// #define BARLEV 9
|
||||
|
@ -469,7 +529,7 @@ bool isAlchAny(eWall w);
|
|||
bool isAlchAny(cell *c);
|
||||
|
||||
#define YDIST 101
|
||||
#define MODECODES 38
|
||||
#define MODECODES 254
|
||||
|
||||
extern cellwalker cwt; // player character position
|
||||
extern int sval;
|
||||
|
@ -494,10 +554,14 @@ bool hellUnlocked();
|
|||
|
||||
bool markOrb(eItem it); // mark the orb as 'used', return true if exists
|
||||
bool markEmpathy(eItem it); // mark both the given orb and Empathy as 'used', return true if exists
|
||||
bool markEmpathy2(eItem it); // as above, but next turn
|
||||
|
||||
bool isMimic(eMonster m);
|
||||
bool isMimic(cell *c);
|
||||
void killWithMessage(cell *c, bool orStun = false, eMonster killer = moNone);
|
||||
|
||||
void fallMonster(cell *c, flagtype flags = 0); // kill monster due to terrain
|
||||
|
||||
bool attackMonster(cell *c, flagtype flags, eMonster killer);
|
||||
|
||||
bool isWorm(eMonster m);
|
||||
bool isWorm(cell *c);
|
||||
|
@ -507,10 +571,11 @@ bool isIvy(cell *c);
|
|||
|
||||
#define GUNRANGE 3
|
||||
|
||||
// 0 = basic treasure, 1 = something else, 2 = power orb
|
||||
// 0 = basic treasure, 1 = other item, 2 = power orb, 3 = not an item
|
||||
#define IC_TREASURE 0
|
||||
#define IC_OTHER 1
|
||||
#define IC_ORB 2
|
||||
#define IC_NAI 3
|
||||
|
||||
bool playerInPower();
|
||||
void activateFlash();
|
||||
|
@ -528,7 +593,7 @@ int realstuntime(cell *c);
|
|||
|
||||
extern bool invismove, invisfish;
|
||||
bool attackingForbidden(cell *c, cell *c2);
|
||||
void killOrStunMonster(cell *c2);
|
||||
void killOrStunMonster(cell *c2, eMonster who_killed);
|
||||
|
||||
extern vector<cell*> offscreen; // offscreen cells to take care off
|
||||
|
||||
|
@ -538,6 +603,8 @@ cell *playerpos(int i);
|
|||
bool makeflame(cell *c, int timeout, bool checkonly);
|
||||
void bfs();
|
||||
bool isPlayerInBoatOn(cell *c);
|
||||
bool isPlayerInBoatOn(cell *c, int i);
|
||||
void destroyBoats(cell *c, cell *cf, bool strandedToo);
|
||||
extern bool showoff;
|
||||
extern int lastexplore;
|
||||
extern int truelotus;
|
||||
|
@ -583,7 +650,18 @@ bool withRose(cell *cfrom, cell *cto);
|
|||
#define MF_MOUNT (1<<18) // don't do
|
||||
#define MF_NOFRIEND (1<<19) // don't do it for friends
|
||||
|
||||
bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, int flags);
|
||||
#define AF_SWORD (1<<20) // big sword
|
||||
#define AF_SWORD_INTO (1<<21) // moving into big sword
|
||||
#define AF_MSG (1<<22) // produce a message
|
||||
#define AF_ORSTUN (1<<23) // attackMonster: allow stunning
|
||||
#define AF_NEXTTURN (1<<24) // next turn -- don't count shield at power 1
|
||||
#define AF_FALL (1<<25) // death by falling
|
||||
#define MF_STUNNED (1<<26) // edgeunstable: ignore ladders (as stunned monsters do)
|
||||
#define MF_IVY (1<<27) // edgeunstable: ignore ivy (ivy cannot climb ivy)
|
||||
#define AF_HORNS (1<<28) // spear attack (always has APPROACH too)
|
||||
#define AF_BULL (1<<29) // bull attack
|
||||
|
||||
bool canAttack(cell *c1, eMonster m1, cell *c2, eMonster m2, flagtype flags);
|
||||
|
||||
extern bool chaosmode;
|
||||
extern bool chaosUnlocked;
|
||||
|
@ -594,22 +672,6 @@ int getGhostcount();
|
|||
void raiseBuggyGeneration(cell *c, const char *s);
|
||||
void verifyMutantAround(cell *c);
|
||||
|
||||
extern FILE *debugfile;
|
||||
extern int debugflags;
|
||||
extern bool offline;
|
||||
|
||||
#ifdef ANDROID
|
||||
#define DEBB(r,x)
|
||||
#else
|
||||
#define DEBB(r,x) { if(debugfile && (!(r) || (debugflags & (r)))) { fprintf x; fflush(debugfile); } }
|
||||
#endif
|
||||
|
||||
#define DF_INIT 0 // always display these
|
||||
#define DF_MSG 0 // always display these
|
||||
#define DF_STEAM 1
|
||||
#define DF_GRAPH 2
|
||||
#define DF_TURN 4
|
||||
|
||||
#ifdef MOBILE
|
||||
#define NOPNG
|
||||
#endif
|
||||
|
@ -633,7 +695,8 @@ void buildAirmap();
|
|||
// currently works for worms only
|
||||
bool sameMonster(cell *c1, cell *c2);
|
||||
cell *wormhead(cell *c);
|
||||
eMonster getMount();
|
||||
eMonster getMount(int player_id);
|
||||
eMonster haveMount();
|
||||
|
||||
bool isDragon(eMonster m);
|
||||
|
||||
|
@ -647,6 +710,8 @@ extern bool autocheat;
|
|||
extern bool inHighQual;
|
||||
|
||||
void mountmove(cell *c, int spin, bool fp);
|
||||
void mountmove(cell *c, int spin, bool fp, cell *ppos);
|
||||
void mountswap(cell *c1, int spin1, bool fp1, cell *c2, int spin2, bool fp2);
|
||||
|
||||
template<class T> struct dynamicval {
|
||||
T& where;
|
||||
|
@ -655,18 +720,403 @@ template<class T> struct dynamicval {
|
|||
~dynamicval() { where = backup; }
|
||||
};
|
||||
|
||||
namespace stalemate {
|
||||
struct stalemate1 {
|
||||
eMonster who;
|
||||
cell *moveto;
|
||||
cell *killed;
|
||||
cell *pushto;
|
||||
cell *comefrom;
|
||||
cell *swordlast[2], *swordtransit[2], *swordnext[2];
|
||||
bool isKilled(cell *c);
|
||||
stalemate1(eMonster w, cell *mt, cell *ki, cell *pt, cell *cf) : who(w), moveto(mt), killed(ki), pushto(pt), comefrom(cf) {}
|
||||
};
|
||||
|
||||
namespace stalemate {
|
||||
vector<stalemate1> moves;
|
||||
bool nextturn;
|
||||
|
||||
bool isKilled(cell *c);
|
||||
|
||||
bool anyKilled();
|
||||
bool isMoveto(cell *c);
|
||||
bool isKilledDirectlyAt(cell *c);
|
||||
bool isPushto(cell *c);
|
||||
};
|
||||
|
||||
extern int turncount;
|
||||
|
||||
bool reduceOrbPower(eItem it, int cap);
|
||||
bool checkOrb(eMonster m1, eItem orb);
|
||||
|
||||
movedir vectodir(const hyperpoint& P);
|
||||
|
||||
namespace sword {
|
||||
|
||||
extern int angle[MAXPLAYER];
|
||||
|
||||
cell *pos(cell *c, int s);
|
||||
cell *pos(int id);
|
||||
bool at(cell *where, bool noplayer = false);
|
||||
int shift(cell *c1, cell *c2);
|
||||
}
|
||||
|
||||
void killThePlayer(eMonster m, int id, flagtype flags);
|
||||
bool attackJustStuns(cell *c2);
|
||||
|
||||
bool isTargetOrAdjacent(cell *c);
|
||||
bool warningprotection();
|
||||
bool mineMarked(cell *c);
|
||||
bool minesafe();
|
||||
bool hasSafeOrb(cell *c);
|
||||
void placeWater(cell *c, cell *c2);
|
||||
bool againstCurrent(cell *w, cell *from);
|
||||
|
||||
#define DEFAULTCONTROL (multi::players == 1 && !shmup::on && !multi::alwaysuse)
|
||||
|
||||
extern bool timerghost;
|
||||
|
||||
#ifdef PANDORA
|
||||
#define MENU_SCALING
|
||||
#endif
|
||||
|
||||
#ifdef MOBILE
|
||||
#define MENU_SCALING
|
||||
#endif
|
||||
|
||||
#ifdef MENU_SCALING
|
||||
#define displayfrZ dialog::displayzoom
|
||||
#else
|
||||
#define displayfrZ displayfr
|
||||
#endif
|
||||
|
||||
namespace dialog {
|
||||
|
||||
enum tDialogItem {diTitle, diItem, diBreak, diHelp, diInfo, diSlider};
|
||||
|
||||
struct item {
|
||||
tDialogItem type;
|
||||
string body;
|
||||
string value;
|
||||
string keycaption;
|
||||
int key;
|
||||
int color, colorv, colork, colors, colorc;
|
||||
int scale;
|
||||
double param;
|
||||
};
|
||||
|
||||
item& lastItem();
|
||||
|
||||
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 addHelp(string body);
|
||||
void addInfo(string body, int color = 0xC0C0C0);
|
||||
void addItem(string body, int key);
|
||||
void addBreak(int val);
|
||||
void addTitle(string body, int color, int scale);
|
||||
|
||||
void init();
|
||||
void init(string title, int color = 0xE8E8E8, int scale = 150, int brk = 60);
|
||||
void display();
|
||||
|
||||
void drawColorDialog(int color);
|
||||
int handleKeyColor(int sym, int uni, int& color);
|
||||
|
||||
void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help);
|
||||
void editNumber(int& x, int vmin, int vmax, int step, int dft, string title, string help);
|
||||
void scaleLog();
|
||||
void scaleSinh();
|
||||
void handleNavigation(int &sym, int &uni);
|
||||
bool displayzoom(int x, int y, int b, int size, const string &s, int color, int align);
|
||||
bool editingDetail();
|
||||
|
||||
int handlePage(int& nl, int& nlm, int perpage);
|
||||
void displayPageButtons(int i, bool pages);
|
||||
bool handlePageButtons(int uni);
|
||||
}
|
||||
|
||||
void checkStunKill(cell *dest);
|
||||
|
||||
void clearMessages();
|
||||
|
||||
void resetGeometry();
|
||||
|
||||
namespace svg {
|
||||
void circle(int x, int y, int size, int col);
|
||||
void polygon(int *polyx, int *polyy, int polyi, int col, int outline);
|
||||
void text(int x, int y, int size, const string& str, bool frame, int col, int align);
|
||||
extern bool in;
|
||||
extern string *info;
|
||||
void render(const char *fname = NULL);
|
||||
}
|
||||
|
||||
extern int sightrange;
|
||||
|
||||
namespace halloween {
|
||||
void getTreat(cell *where);
|
||||
}
|
||||
|
||||
// just in case if I change my mind about when Orbs lose their power
|
||||
#define ORBBASE 0
|
||||
|
||||
transmatrix mscale(const transmatrix& t, double fac);
|
||||
transmatrix mzscale(const transmatrix& t, double fac);
|
||||
extern bool ivoryz;
|
||||
#define mmscale(V, x) (mmspatial ? (ivoryz ? mzscale(V,x) : mscale(V, x)) : (V))
|
||||
|
||||
#define SHADOW_WALL 0x60
|
||||
#define SHADOW_SL 0x18
|
||||
#define SHADOW_MON 0x30
|
||||
|
||||
bool drawMonsterType(eMonster m, cell *where, const transmatrix& V, int col, double footphase);
|
||||
void drawPlayerEffects(const transmatrix& V, cell *c, bool onPlayer);
|
||||
|
||||
// monster movement animations
|
||||
|
||||
struct animation {
|
||||
int ltick;
|
||||
double footphase;
|
||||
transmatrix wherenow;
|
||||
};
|
||||
|
||||
// we need separate animation layers for Orb of Domination and Tentacle+Ghost,
|
||||
// and also to mark Boats
|
||||
#define ANIMLAYERS 3
|
||||
#define LAYER_BIG 0 // for worms and krakens
|
||||
#define LAYER_SMALL 1 // for others
|
||||
#define LAYER_BOAT 2 // mark that a boat has moved
|
||||
|
||||
extern map<cell*, animation> animations[ANIMLAYERS];
|
||||
extern unordered_map<cell*, transmatrix> gmatrix, gmatrix0;
|
||||
|
||||
void animateMovement(cell *src, cell *tgt, int layer);
|
||||
|
||||
// for animations which might use the same locations,
|
||||
// such as replacements or multi-tile monsters
|
||||
void indAnimateMovement(cell *src, cell *tgt, int layer);
|
||||
void commitAnimations(int layer);
|
||||
|
||||
void animateReplacement(cell *a, cell *b, int layer);
|
||||
void fallingFloorAnimation(cell *c, eWall w = waNone, eMonster m = moNone);
|
||||
void fallingMonsterAnimation(cell *c, eMonster m);
|
||||
|
||||
// ranks:
|
||||
enum PPR {
|
||||
PPR_ZERO, PPR_OUTCIRCLE, PPR_MOVESTAR,
|
||||
PPR_MINUSINF,
|
||||
PPR_BELOWBOTTOMm,
|
||||
PPR_BELOWBOTTOM,
|
||||
PPR_BELOWBOTTOMp,
|
||||
PPR_LAKEBOTTOM, PPR_HELLSPIKE,
|
||||
PPR_INLAKEWALLm, PPR_INLAKEWALL, PPR_INLAKEWALLp,
|
||||
PPR_SUBLAKELEV, PPR_LAKELEV, PPR_BOATLEV, PPR_BOATLEV2, PPR_BOATLEV3,
|
||||
PPR_LAKEWALLm, PPR_LAKEWALL, PPR_LAKEWALLp,
|
||||
PPR_FLOOR_TOWER,
|
||||
PPR_FLOOR,
|
||||
PPR_FLOOR_DRAGON,
|
||||
PPR_FLOORa, PPR_FLOORb, PPR_FLOORc, PPR_FLOORd,
|
||||
PPR_LIZEYE,
|
||||
PPR_BFLOOR,
|
||||
PPR_GFLOORa, PPR_GFLOORb, PPR_GFLOORc,
|
||||
PPR_WALLSHADOW,
|
||||
PPR_STRUCT0, PPR_STRUCT1, PPR_STRUCT2, PPR_STRUCT3,
|
||||
PPR_THORNS, PPR_WALL,
|
||||
PPR_REDWALLm, PPR_REDWALLs, PPR_REDWALLp, PPR_REDWALL,
|
||||
PPR_REDWALLm2, PPR_REDWALLs2, PPR_REDWALLp2, PPR_REDWALLt2,
|
||||
PPR_REDWALLm3, PPR_REDWALLs3, PPR_REDWALLp3, PPR_REDWALLt3,
|
||||
PPR_HEPTAMARK,
|
||||
PPR_ITEM, PPR_ITEMa, PPR_ITEMb,
|
||||
PPR_BIGSTATUE,
|
||||
PPR_GLASSm, PPR_GLASSs, PPR_GLASSp, PPR_GLASS,
|
||||
PPR_WALL3m, PPR_WALL3s, PPR_WALL3p, PPR_WALL3, PPR_WALL3A,
|
||||
PPR_HIDDEN, PPR_GIANTSHADOW,
|
||||
PPR_TENTACLE0, PPR_TENTACLE1,
|
||||
PPR_ONTENTACLE, PPR_ONTENTACLE_EYES, PPR_ONTENTACLE_EYES2,
|
||||
PPR_MONSTER_SHADOW,
|
||||
PPR_MONSTER_FOOT, PPR_MONSTER_LEG, PPR_MONSTER_GROIN,
|
||||
PPR_MONSTER_BODY, PPR_MONSTER_SUBWPN, PPR_MONSTER_WPN, PPR_MONSTER_ARMOR0, PPR_MONSTER_ARMOR1,
|
||||
PPR_MONSTER_CLOAK, PPR_MONSTER_NECK,
|
||||
PPR_MONSTER_HEAD, PPR_MONSTER_FACE, PPR_MONSTER_EYE0, PPR_MONSTER_EYE1,
|
||||
PPR_MONSTER_HAIR, PPR_MONSTER_HAT0, PPR_MONSTER_HAT1,
|
||||
PPR_MONSTER_HOODCLOAK1, PPR_MONSTER_HOODCLOAK2,
|
||||
PPR_STUNSTARS,
|
||||
PPR_CARRIED, PPR_CARRIEDa, PPR_CARRIEDb,
|
||||
PPR_PARTICLE, PPR_SWORDMARK, PPR_MAGICSWORD, PPR_MISSILE,
|
||||
PPR_MINEMARK, PPR_ARROW,
|
||||
PPR_LINE, PPR_TEXT, PPR_CIRCLE,
|
||||
PPR_MAX
|
||||
};
|
||||
|
||||
void ShadowV(const transmatrix& V, const struct hpcshape& bp, int prio = PPR_MONSTER_SHADOW);
|
||||
|
||||
#define OUTLINE_NONE 0x000000FF
|
||||
#define OUTLINE_FRIEND 0x00FF00FF
|
||||
#define OUTLINE_ENEMY 0xFF0000FF
|
||||
#define OUTLINE_TREASURE 0xFFFF00FF
|
||||
#define OUTLINE_ORB 0xFF8000FF
|
||||
#define OUTLINE_OTHER 0xFFFFFFFF
|
||||
#define OUTLINE_DEAD 0x800000FF
|
||||
#define OUTLINE_TRANS 0
|
||||
|
||||
extern bool audio;
|
||||
extern string musiclicense;
|
||||
extern string musfname[landtypes];
|
||||
extern int musicvolume, effvolume;
|
||||
void initAudio();
|
||||
bool loadMusicInfo();
|
||||
void handlemusic();
|
||||
void playSeenSound(cell *c);
|
||||
void playSound(cell *c, const string& fname, int vol = 100);
|
||||
|
||||
inline string pick123() { return cts('1' + rand() % 3); }
|
||||
inline string pick12() { return cts('1' + rand() % 2); }
|
||||
|
||||
bool playerInBoat(int i);
|
||||
|
||||
extern int lowfar;
|
||||
extern bool wmspatial, wmescher, wmplain, wmblack, wmascii;
|
||||
extern bool mmspatial, mmhigh, mmmon, mmitem;
|
||||
extern int maxreclevel, reclevel;
|
||||
|
||||
string explain3D(ld *param);
|
||||
|
||||
extern int detaillevel;
|
||||
extern bool quitmainloop;
|
||||
|
||||
enum eGlyphsortorder {
|
||||
gsoFirstTop, gsoFirstBottom,
|
||||
gsoLastTop, gsoLastBottom,
|
||||
gsoLand, gsoValue,
|
||||
gsoMAX
|
||||
};
|
||||
|
||||
extern eGlyphsortorder glyphsortorder;
|
||||
|
||||
#ifdef ROGUEVIZ
|
||||
namespace rogueviz {
|
||||
extern bool on;
|
||||
string describe(shmup::monster *m);
|
||||
void activate(shmup::monster *m);
|
||||
void drawVertex(const transmatrix &V, cell *c, shmup::monster *m);
|
||||
bool virt(shmup::monster *m);
|
||||
void turn(int delta);
|
||||
void drawExtra();
|
||||
void fixparam();
|
||||
int readArgs();
|
||||
void close();
|
||||
}
|
||||
#endif
|
||||
|
||||
void explodeMine(cell *c);
|
||||
bool mayExplodeMine(cell *c, eMonster who);
|
||||
|
||||
int gravityLevel(cell *c);
|
||||
void fullcenter();
|
||||
void movecost(cell* from, cell *to);
|
||||
void checkmove();
|
||||
|
||||
transmatrix eumove(int x, int y);
|
||||
|
||||
#ifndef NOSAVE
|
||||
void loadScores();
|
||||
#endif
|
||||
|
||||
int reptilemax();
|
||||
|
||||
extern bool mousing;
|
||||
#define IFM(x) (mousing?"":x)
|
||||
|
||||
extern cell *recallCell;
|
||||
|
||||
extern eLand cheatdest;
|
||||
void cheatMoveTo(eLand l);
|
||||
|
||||
extern int backcolor;
|
||||
|
||||
extern bool overgenerate;
|
||||
void doOvergenerate();
|
||||
|
||||
void collectMessage(cell *c2, eItem which);
|
||||
|
||||
namespace quotientspace {
|
||||
void build();
|
||||
void clear();
|
||||
extern vector<int> connections;
|
||||
}
|
||||
|
||||
void killFriendlyIvy();
|
||||
|
||||
void pushdown(cell *c, int& q, const transmatrix &V, double down, bool rezoom, bool repriority);
|
||||
|
||||
extern bool viewdists;
|
||||
|
||||
void preventbarriers(cell *c);
|
||||
|
||||
bool passable_for(eMonster m, cell *w, cell *from, flagtype extra);
|
||||
|
||||
void beastcrash(cell *c, cell *beast);
|
||||
|
||||
int angledist(int t, int d1, int d2);
|
||||
int angledist(cell *c, int d1, int d2);
|
||||
|
||||
void setcameraangle(bool b);
|
||||
|
||||
enum eModel {
|
||||
mdDisk, mdHalfplane, mdBand, mdPolygonal, mdPolynomial,
|
||||
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid, mdGUARD, mdUnchanged };
|
||||
|
||||
#define MODELCOUNT ((int) mdGUARD)
|
||||
|
||||
void drawShape(pair<ld,ld>* coords, int qty, int color);
|
||||
|
||||
extern eModel pmodel;
|
||||
|
||||
int darkena(int c, int lev, int a);
|
||||
|
||||
#define SHSIZE 16
|
||||
|
||||
extern cell *shpos[MAXPLAYER][SHSIZE];
|
||||
extern int cshpos;
|
||||
|
||||
|
||||
namespace arg {
|
||||
#ifdef USE_COMMANDLINE
|
||||
extern int argc; extern char **argv;
|
||||
|
||||
inline void lshift() {
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
inline void shift() {
|
||||
lshift(); if(!argc) { printf("Missing parameter\n"); exit(1); }
|
||||
}
|
||||
|
||||
inline char* args() { return *argv; }
|
||||
inline int argi() { return atoi(*argv); }
|
||||
inline ld argf() { return atof(*argv); }
|
||||
inline bool argis(const char *s) { return strcmp(*argv, s) == 0; }
|
||||
|
||||
inline void init(int _argc, char **_argv) { argc=_argc-1; argv=_argv+1; }
|
||||
|
||||
int curphase;
|
||||
|
||||
inline void phaseerror(int x) {
|
||||
printf("Command line error: cannot read command '%s' from phase %d in phase %d\n", args(), x, curphase);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// returned values: 0 = ok, 1 = not recognized, 2 = shift phase
|
||||
int readCommon();
|
||||
int readLocal();
|
||||
|
||||
// an useful macro
|
||||
#define PHASE(x) { if(arg::curphase > x) phaseerror(x); else if(arg::curphase < x) return 2; }
|
||||
|
||||
void read(int phase);
|
||||
|
||||
#else
|
||||
inline void read(int phase) { }
|
||||
#endif
|
||||
}
|
||||
|
||||
extern bool generatingEquidistant;
|
||||
|
|
283
hyperpoint.cpp
283
hyperpoint.cpp
|
@ -1,29 +1,12 @@
|
|||
// Hyperbolic Rogue
|
||||
// Copyright (C) 2011-2012 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
// basic utility functions
|
||||
|
||||
#ifdef MOBILE
|
||||
typedef double ld;
|
||||
#else
|
||||
typedef long double ld;
|
||||
#endif
|
||||
|
||||
template<class T> int size(const T& x) {return int(x.size()); }
|
||||
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 fts4(float x) { char buf[64]; sprintf(buf, "%6.4f", 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
|
||||
if(i < 0) return "-" + llts(-i);
|
||||
if(i < 10) return its((int) i);
|
||||
return llts(i/10) + its(i%10);
|
||||
}
|
||||
string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
|
||||
|
||||
// for the Euclidean mode...
|
||||
bool euclid = false;
|
||||
enum eGeometry {gNormal, gEuclid, gSphere, gElliptic, gQuotient, gQuotient2, gGUARD};
|
||||
eGeometry geometry, targetgeometry = gEuclid;
|
||||
#define euclid (geometry == gEuclid)
|
||||
#define sphere (geometry == gSphere || geometry == gElliptic)
|
||||
#define elliptic (geometry == gElliptic)
|
||||
#define quotient (geometry == gQuotient ? 1 : geometry == gQuotient2 ? 2 : 0)
|
||||
|
||||
// for the pure heptagonal grid
|
||||
bool purehepta = false;
|
||||
|
@ -34,13 +17,31 @@ bool purehepta = false;
|
|||
//===========================
|
||||
|
||||
#ifdef SINHCOSH
|
||||
ld sinh(ld alpha) { return (exp(alpha) - exp(-alpha)) / 2; }
|
||||
ld cosh(ld alpha) { return (exp(alpha) + exp(-alpha)) / 2; }
|
||||
// ld sinh(ld alpha) { return (exp(alpha) - exp(-alpha)) / 2; }
|
||||
// ld cosh(ld alpha) { return (exp(alpha) + exp(-alpha)) / 2; }
|
||||
|
||||
/* ld inverse_sinh(ld z) {
|
||||
return log(z+sqrt(1+z*z));
|
||||
}
|
||||
|
||||
double inverse_cos(double c) {
|
||||
double s = sqrt(1-c*c);
|
||||
double r = atan(s/c);
|
||||
if(r < 0) r = -r;
|
||||
return r;
|
||||
}
|
||||
|
||||
// ld tanh(ld x) { return sinh(x) / cosh(x); }
|
||||
ld inverse_tanh(ld x) { return log((1+x)/(1-x)) / 2; } */
|
||||
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979
|
||||
#endif
|
||||
|
||||
ld squar(ld x) { return x*x; }
|
||||
|
||||
int sig(int z) { return z<2?1:-1; }
|
||||
int sig(int z) { return (sphere || z<2)?1:-1; }
|
||||
|
||||
// hyperbolic point:
|
||||
//===================
|
||||
|
@ -62,17 +63,17 @@ hyperpoint hpxyz(ld x, ld y, ld z) {
|
|||
|
||||
hyperpoint hpxy(ld x, ld y) {
|
||||
// EUCLIDEAN
|
||||
return hpxyz(x,y, euclid ? 1 : sqrt(1+x*x+y*y));
|
||||
return hpxyz(x,y, euclid ? 1 : sphere ? sqrt(1-x*x-y*y) : sqrt(1+x*x+y*y));
|
||||
}
|
||||
|
||||
// center of the pseudosphere
|
||||
hyperpoint Hypc = { {0,0,0} };
|
||||
const hyperpoint Hypc = { {0,0,0} };
|
||||
|
||||
// origin of the hyperbolic plane
|
||||
hyperpoint C0 = { {0,0,1} };
|
||||
const hyperpoint C0 = { {0,0,1} };
|
||||
|
||||
// a point (I hope this number needs no comments ;) )
|
||||
hyperpoint Cx1 = { {1,0,1.41421356237} };
|
||||
const hyperpoint Cx1 = { {1,0,1.41421356237} };
|
||||
|
||||
// this function returns approximate square of distance between two points
|
||||
// (in the spherical analogy, this would be the distance in the 3D space,
|
||||
|
@ -80,7 +81,17 @@ hyperpoint Cx1 = { {1,0,1.41421356237} };
|
|||
// also used to verify whether a point h1 is on the hyperbolic plane by using Hypc for h2
|
||||
|
||||
ld intval(const hyperpoint &h1, const hyperpoint &h2) {
|
||||
return squar(h1[0]-h2[0]) + squar(h1[1]-h2[1]) - squar(h1[2]-h2[2]);
|
||||
return squar(h1[0]-h2[0]) + squar(h1[1]-h2[1]) + (sphere?1:euclid?0:-1) * squar(h1[2]-h2[2]);
|
||||
}
|
||||
|
||||
ld intvalxy(const hyperpoint &h1, const hyperpoint &h2) {
|
||||
return squar(h1[0]-h2[0]) + squar(h1[1]-h2[1]);
|
||||
}
|
||||
|
||||
ld zlevel(const hyperpoint &h) {
|
||||
if(euclid) return h[2];
|
||||
else if(sphere) return sqrt(intval(h, Hypc));
|
||||
else return sqrt(-intval(h, Hypc));
|
||||
}
|
||||
|
||||
// display a hyperbolic point
|
||||
|
@ -100,7 +111,8 @@ hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
|
|||
|
||||
ld Z = 2;
|
||||
|
||||
if(!euclid) {
|
||||
if(sphere) Z = sqrt(intval(H3, Hypc));
|
||||
else if(!euclid) {
|
||||
Z = intval(H3, Hypc);
|
||||
Z = sqrt(-Z);
|
||||
}
|
||||
|
@ -110,42 +122,20 @@ hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
|
|||
return H3;
|
||||
}
|
||||
|
||||
hyperpoint mid3(const hyperpoint& H1, const hyperpoint& H2, const hyperpoint& H3) {
|
||||
// like mid, but take 3D into account
|
||||
hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) {
|
||||
|
||||
hyperpoint Hx;
|
||||
Hx[0] = H1[0] + H2[0] + H3[0];
|
||||
Hx[1] = H1[1] + H2[1] + H3[1];
|
||||
Hx[2] = H1[2] + H2[2] + H3[2];
|
||||
hyperpoint H3;
|
||||
H3[0] = H1[0] + H2[0];
|
||||
H3[1] = H1[1] + H2[1];
|
||||
H3[2] = H1[2] + H2[2];
|
||||
|
||||
ld Z = 2;
|
||||
|
||||
if(!euclid) {
|
||||
Z = intval(Hx, Hypc);
|
||||
Z = sqrt(-Z);
|
||||
}
|
||||
if(sphere || !euclid) Z = zlevel(H3) * 2 / (zlevel(H1) + zlevel(H2));
|
||||
for(int c=0; c<3; c++) H3[c] /= Z;
|
||||
|
||||
for(int c=0; c<3; c++) Hx[c] /= Z;
|
||||
|
||||
return Hx;
|
||||
}
|
||||
|
||||
hyperpoint mid4(const hyperpoint& H1, const hyperpoint& H2, const hyperpoint& H3, const hyperpoint& H4) {
|
||||
|
||||
hyperpoint Hx;
|
||||
Hx[0] = H1[0] + H2[0] + H3[0] + H4[0];
|
||||
Hx[1] = H1[1] + H2[1] + H3[1] + H4[1];
|
||||
Hx[2] = H1[2] + H2[2] + H3[2] + H4[2];
|
||||
|
||||
ld Z = 2;
|
||||
|
||||
if(!euclid) {
|
||||
Z = intval(Hx, Hypc);
|
||||
Z = sqrt(-Z);
|
||||
}
|
||||
|
||||
for(int c=0; c<3; c++) Hx[c] /= Z;
|
||||
|
||||
return Hx;
|
||||
return H3;
|
||||
}
|
||||
|
||||
// matrices
|
||||
|
@ -161,9 +151,13 @@ struct transmatrix {
|
|||
};
|
||||
|
||||
// identity matrix
|
||||
transmatrix Id = {{{1,0,0}, {0,1,0}, {0,0,1}}};
|
||||
const transmatrix Id = {{{1,0,0}, {0,1,0}, {0,0,1}}};
|
||||
|
||||
transmatrix Mirror = {{{1,0,0}, {0,-1,0}, {0,0,1}}};
|
||||
// mirror image
|
||||
const transmatrix Mirror = {{{1,0,0}, {0,-1,0}, {0,0,1}}};
|
||||
|
||||
// rotate by PI
|
||||
const transmatrix pispin = {{{-1,0,0}, {0,-1,0}, {0,0,1}}};
|
||||
|
||||
hyperpoint operator * (const transmatrix& T, const hyperpoint& H) {
|
||||
hyperpoint z;
|
||||
|
@ -174,11 +168,18 @@ hyperpoint operator * (const transmatrix& T, const hyperpoint& H) {
|
|||
return z;
|
||||
}
|
||||
|
||||
transmatrix operator * (const transmatrix& T, const transmatrix& U) {
|
||||
// T * C0, optimized
|
||||
inline hyperpoint tC0(const transmatrix &T) {
|
||||
hyperpoint z;
|
||||
z[0] = T[0][2]; z[1] = T[1][2]; z[2] = T[2][2];
|
||||
return z;
|
||||
}
|
||||
|
||||
inline transmatrix operator * (const transmatrix& T, const transmatrix& U) {
|
||||
transmatrix R;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++) R[i][j] = 0;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++) for(int k=0; k<3; k++)
|
||||
R[i][j] += T[i][k] * U[k][j];
|
||||
// for(int i=0; i<3; i++) for(int j=0; j<3; j++) R[i][j] = 0;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++) // for(int k=0; k<3; k++)
|
||||
R[i][j] = T[i][0] * U[0][j] + T[i][1] * U[1][j] + T[i][2] * U[2][j];
|
||||
return R;
|
||||
}
|
||||
|
||||
|
@ -202,26 +203,52 @@ transmatrix eupush(ld x, ld y) {
|
|||
transmatrix xpush(ld alpha) {
|
||||
if(euclid) return eupush(alpha, 0);
|
||||
transmatrix T = Id;
|
||||
T[0][0] = +cosh(alpha); T[0][2] = +sinh(alpha);
|
||||
T[2][0] = +sinh(alpha); T[2][2] = +cosh(alpha);
|
||||
if(sphere) {
|
||||
T[0][0] = +cos(alpha); T[0][2] = +sin(alpha);
|
||||
T[2][0] = -sin(alpha); T[2][2] = +cos(alpha);
|
||||
}
|
||||
else {
|
||||
T[0][0] = +cosh(alpha); T[0][2] = +sinh(alpha);
|
||||
T[2][0] = +sinh(alpha); T[2][2] = +cosh(alpha);
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
double inverse_sinh(ld z) {
|
||||
return log(z+sqrt(1+z*z));
|
||||
inline hyperpoint xpush0(ld x) {
|
||||
hyperpoint h;
|
||||
if(euclid) return hpxy(x, 0);
|
||||
else if(sphere) h[0] = sin(x), h[1] = 0, h[2] = cos(x);
|
||||
else h[0] = sinh(x), h[1] = 0, h[2] = cosh(x);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
inline hyperpoint xspinpush0(ld alpha, ld x) {
|
||||
// return spin(alpha)*xpush0(x);
|
||||
ld s;
|
||||
hyperpoint h;
|
||||
if(euclid) return hpxy(x*cos(alpha), -x*sin(alpha));
|
||||
else if(sphere) s=sin(x), h[0] = s*cos(alpha), h[1] = -s*sin(alpha), h[2] = cos(x);
|
||||
else s=sinh(x), h[0] = s*cos(alpha), h[1] = -s*sin(alpha), h[2] = cosh(x);
|
||||
return h;
|
||||
}
|
||||
|
||||
// push alpha units vertically
|
||||
transmatrix ypush(ld alpha) {
|
||||
if(euclid) return eupush(0, alpha);
|
||||
transmatrix T = Id;
|
||||
T[1][1] = +cosh(alpha); T[1][2] = +sinh(alpha);
|
||||
T[2][1] = +sinh(alpha); T[2][2] = +cosh(alpha);
|
||||
if(sphere) {
|
||||
T[1][1] = +cos(alpha); T[1][2] = +sin(alpha);
|
||||
T[2][1] = -sin(alpha); T[2][2] = +cos(alpha);
|
||||
}
|
||||
else {
|
||||
T[1][1] = +cosh(alpha); T[1][2] = +sinh(alpha);
|
||||
T[2][1] = +sinh(alpha); T[2][2] = +cosh(alpha);
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
// rotate the hyperplane around C0 such that H[1] == 0 and H[0] >= 0
|
||||
transmatrix spintox(hyperpoint H) {
|
||||
transmatrix spintox(const hyperpoint& H) {
|
||||
transmatrix T = Id;
|
||||
ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||
if(R >= 1e-12) {
|
||||
|
@ -232,7 +259,7 @@ transmatrix spintox(hyperpoint H) {
|
|||
}
|
||||
|
||||
// reverse of spintox(H)
|
||||
transmatrix rspintox(hyperpoint H) {
|
||||
transmatrix rspintox(const hyperpoint& H) {
|
||||
transmatrix T = Id;
|
||||
ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||
if(R >= 1e-12) {
|
||||
|
@ -243,30 +270,42 @@ transmatrix rspintox(hyperpoint H) {
|
|||
}
|
||||
|
||||
// for H such that H[1] == 0, this matrix pushes H to C0
|
||||
transmatrix pushxto0(hyperpoint H) {
|
||||
transmatrix pushxto0(const hyperpoint& H) {
|
||||
if(euclid) return eupush(-H[0], -H[1]);
|
||||
transmatrix T = Id;
|
||||
T[0][0] = +H[2]; T[0][2] = -H[0];
|
||||
T[2][0] = -H[0]; T[2][2] = +H[2];
|
||||
if(sphere) {
|
||||
T[0][0] = +H[2]; T[0][2] = -H[0];
|
||||
T[2][0] = +H[0]; T[2][2] = +H[2];
|
||||
}
|
||||
else {
|
||||
T[0][0] = +H[2]; T[0][2] = -H[0];
|
||||
T[2][0] = -H[0]; T[2][2] = +H[2];
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
// reverse of pushxto0(H)
|
||||
transmatrix rpushxto0(hyperpoint H) {
|
||||
transmatrix rpushxto0(const hyperpoint& H) {
|
||||
if(euclid) return eupush(H[0], H[1]);
|
||||
transmatrix T = Id;
|
||||
T[0][0] = +H[2]; T[0][2] = +H[0];
|
||||
T[2][0] = +H[0]; T[2][2] = +H[2];
|
||||
if(sphere) {
|
||||
T[0][0] = +H[2]; T[0][2] = +H[0];
|
||||
T[2][0] = -H[0]; T[2][2] = +H[2];
|
||||
}
|
||||
else {
|
||||
T[0][0] = +H[2]; T[0][2] = +H[0];
|
||||
T[2][0] = +H[0]; T[2][2] = +H[2];
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
// generalization: H[1] can be non-zero
|
||||
transmatrix gpushxto0(hyperpoint H) {
|
||||
transmatrix gpushxto0(const hyperpoint& H) {
|
||||
hyperpoint H2 = spintox(H) * H;
|
||||
return rspintox(H) * pushxto0(H2) * spintox(H);
|
||||
}
|
||||
|
||||
transmatrix rgpushxto0(hyperpoint H) {
|
||||
transmatrix rgpushxto0(const hyperpoint& H) {
|
||||
hyperpoint H2 = spintox(H) * H;
|
||||
return rspintox(H) * rpushxto0(H2) * spintox(H);
|
||||
}
|
||||
|
@ -305,18 +344,22 @@ void fixmatrix(transmatrix& T) {
|
|||
void display(const transmatrix& T) {
|
||||
for(int y=0; y<3; y++) {
|
||||
for(int x=0; x<3; x++) printf("%10.7f", double(T[y][x]));
|
||||
printf(" -> %10.7f\n", double(squar(T[y][0]) + squar(T[y][1]) - squar(T[y][2])));
|
||||
printf(" -> %10.7f\n", double(squar(T[y][0]) + squar(T[y][1]) + sig(2) * squar(T[y][2])));
|
||||
// printf("\n");
|
||||
}
|
||||
for(int x=0; x<3; x++) printf("%10.7f", double(squar(T[0][x]) + squar(T[1][x]) - squar(T[2][x]))); printf("\n");
|
||||
|
||||
for(int x=0; x<3; x++) printf("%10.7f", double(squar(T[0][x]) + squar(T[1][x]) + sig(2) * squar(T[2][x])));
|
||||
printf("\n");
|
||||
|
||||
for(int x=0; x<3; x++) {
|
||||
int y = (x+1) % 3;
|
||||
printf("%10.7f", double(T[0][x]*T[0][y] + T[1][x]*T[1][y] - T[2][x]*T[2][y]));
|
||||
printf("%10.7f", double(T[0][x]*T[0][y] + T[1][x]*T[1][y] + sig(2) * T[2][x]*T[2][y]));
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
transmatrix inverse(transmatrix T) {
|
||||
profile_start(7);
|
||||
ld det = 0;
|
||||
for(int i=0; i<3; i++)
|
||||
det += T[0][i] * T[1][(i+1)%3] * T[2][(i+2)%3];
|
||||
|
@ -330,12 +373,22 @@ transmatrix inverse(transmatrix T) {
|
|||
for(int j=0; j<3; j++)
|
||||
T2[j][i] = (T[(i+1)%3][(j+1)%3] * T[(i+2)%3][(j+2)%3] - T[(i+1)%3][(j+2)%3] * T[(i+2)%3][(j+1)%3]) / det;
|
||||
|
||||
profile_stop(7);
|
||||
return T2;
|
||||
}
|
||||
|
||||
double hdist(hyperpoint h1, hyperpoint h2) {
|
||||
hyperpoint mh = gpushxto0(h1) * h2;
|
||||
return inverse_sinh(sqrt(mh[0]*mh[0]+mh[1]*mh[1]));
|
||||
// distance between mh and 0
|
||||
double hdist0(const hyperpoint& mh) {
|
||||
if(sphere) return mh[2] >= 1 ? 0 : mh[2] <= -1 ? M_PI : acos(mh[2]);
|
||||
if(!euclid && mh[2] > 1.5) return acosh(mh[2]);
|
||||
ld d = sqrt(mh[0]*mh[0]+mh[1]*mh[1]);
|
||||
if(euclid) return d;
|
||||
return asinh(d);
|
||||
}
|
||||
|
||||
// distance between two points
|
||||
double hdist(const hyperpoint& h1, const hyperpoint& h2) {
|
||||
return hdist0(gpushxto0(h1) * h2);
|
||||
}
|
||||
|
||||
namespace hyperpoint_vec {
|
||||
|
@ -361,3 +414,49 @@ namespace hyperpoint_vec {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
hyperpoint mscale(const hyperpoint& t, double fac) {
|
||||
hyperpoint res;
|
||||
for(int i=0; i<3; i++)
|
||||
res[i] = t[i] * fac;
|
||||
return res;
|
||||
}
|
||||
|
||||
transmatrix mscale(const transmatrix& t, double fac) {
|
||||
transmatrix res;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++)
|
||||
res[i][j] = t[i][j] * fac;
|
||||
return res;
|
||||
}
|
||||
|
||||
transmatrix xyscale(const transmatrix& t, double fac) {
|
||||
transmatrix res;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<2; j++)
|
||||
res[i][j] = t[i][j] * fac;
|
||||
return res;
|
||||
}
|
||||
|
||||
transmatrix xyzscale(const transmatrix& t, double fac, double facz) {
|
||||
transmatrix res;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<2; j++)
|
||||
res[i][j] = t[i][j] * fac;
|
||||
for(int i=0; i<3; i++)
|
||||
res[i][2] = t[i][2] * facz;
|
||||
return res;
|
||||
}
|
||||
|
||||
// double downspin_zivory;
|
||||
|
||||
transmatrix mzscale(const transmatrix& t, double fac) {
|
||||
// take only the spin
|
||||
transmatrix tcentered = gpushxto0(tC0(t)) * t;
|
||||
// tcentered = tcentered * spin(downspin_zivory);
|
||||
fac -= 1;
|
||||
transmatrix res = t * inverse(tcentered) * ypush(-fac) * tcentered;
|
||||
fac *= .2;
|
||||
fac += 1;
|
||||
for(int i=0; i<3; i++) for(int j=0; j<3; j++)
|
||||
res[i][j] = res[i][j] * fac;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
#define WEB
|
||||
#define MOBWEB
|
||||
#define MINI
|
||||
#define NOAUDIO
|
||||
#define NOGFX
|
||||
#define NOPNG
|
||||
#define DEMO
|
||||
|
||||
#ifdef FAKEWEB
|
||||
void mainloopiter();
|
||||
template<class A, class B, class C> void emscripten_set_main_loop(A a, B b, C c) { while(true) mainloopiter(); }
|
||||
#else
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
void initweb();
|
||||
|
||||
void loadCompressedChar(int &otwidth, int &otheight, int *tpix);
|
||||
|
||||
#include "hyper.cpp"
|
||||
|
||||
void playSound(cell *c, const string& fname, int vol) { }
|
||||
|
||||
void initweb() {
|
||||
toggleanim(false);
|
||||
cmode = emMenu;
|
||||
}
|
||||
|
||||
unsigned char fonttable[] = {
|
||||
43,13,0,255,0,255,0,49,
|
||||
43,16,0,133,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,236,255,4,235,0,10,206,255,4,205,0,10,176,255,4,175,0,10,146,255,4,145,0,10,116,255,4,115,0,10,86,255,4,85,0,10,55,255,4,55,0,58,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,149,
|
||||
43,19,0,155,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,7,255,4,0,4,255,4,0,255,0,224,
|
||||
43,30,0,251,152,255,3,72,0,3,28,255,3,188,0,17,223,255,2,247,9,0,3,100,255,3,116,0,16,38,255,3,185,0,4,172,255,3,44,0,16,110,255,3,114,0,3,3,239,255,2,227,0,17,181,255,3,42,0,3,60,255,3,156,0,16,7,245,255,2,227,0,4,132,255,3,84,0,11,255,23,0,7,255,23,0,7,255,23,0,7,255,23,0,11,51,255,3,172,0,4,187,255,3,37,0,16,114,255,3,110,0,3,5,244,255,2,230,0,17,176,255,3,47,0,3,56,255,3,169,0,16,1,237,255,2,239,2,0,3,119,255,3,108,0,16,45,255,3,179,0,4,181,255,3,46,0,11,255,23,0,7,255,23,0,7,255,23,0,7,255,23,0,11,70,255,3,157,0,4,207,255,2,252,12,0,16,131,255,3,95,0,3,15,253,255,2,203,0,17,192,255,3,34,0,3,73,255,3,142,0,16,5,246,255,2,229,0,4,134,255,3,81,0,16,57,255,3,168,0,4,195,255,3,21,0,16,117,255,3,107,0,3,7,248,255,2,215,0,17,178,255,3,46,0,3,61,255,3,154,0,255,0,27,
|
||||
43,25,0,186,252,255,2,0,22,253,255,2,0,22,254,255,2,0,22,255,3,0,17,24,102,157,193,216,255,3,233,188,130,64,3,0,10,29,169,252,255,11,236,153,51,0,7,58,240,255,16,0,6,21,236,255,17,0,6,137,255,5,238,111,39,255,3,15,46,97,159,238,255,2,0,6,214,255,5,71,0,2,255,3,0,4,5,83,198,0,6,245,255,5,13,0,2,255,3,0,13,244,255,5,85,0,2,255,3,0,13,209,255,5,244,133,59,255,3,0,13,130,255,11,166,119,71,12,0,9,16,227,255,13,249,186,81,2,0,7,38,213,255,15,196,28,0,7,7,106,212,255,14,215,9,0,9,36,105,157,204,255,11,116,0,13,255,3,121,185,255,6,199,0,13,255,3,0,2,106,255,5,238,0,13,255,3,0,2,15,255,5,248,0,4,206,106,18,0,6,255,3,0,2,40,255,5,224,0,4,255,2,252,196,127,79,35,9,0,1,255,3,14,62,204,255,5,158,0,4,255,8,245,255,10,250,44,0,4,255,18,253,97,0,5,255,17,204,60,0,6,21,62,103,145,181,199,215,232,248,255,3,240,215,178,124,49,0,16,4,255,3,0,21,3,255,3,0,21,2,255,3,0,21,1,255,3,0,22,255,3,0,111,
|
||||
43,36,0,255,0,37,62,163,221,246,246,221,162,62,0,11,11,224,255,2,159,0,10,8,162,255,8,159,7,0,9,141,255,2,235,19,0,10,163,255,10,159,0,8,49,252,255,2,94,0,10,65,255,3,251,109,16,15,109,252,255,3,61,0,6,2,203,255,2,189,0,11,164,255,3,145,0,4,145,255,3,163,0,6,111,255,2,247,37,0,11,223,255,3,47,0,4,48,255,3,222,0,5,28,243,255,2,125,0,12,247,255,3,14,0,4,14,255,3,246,0,5,176,255,2,214,6,0,12,246,255,3,14,0,4,15,255,3,245,0,4,81,255,2,254,61,0,13,222,255,3,48,0,4,49,255,3,221,0,3,13,227,255,2,155,0,14,163,255,3,146,0,4,146,255,3,161,0,3,146,255,2,233,17,0,14,63,255,3,251,108,15,14,107,251,255,3,60,0,2,53,253,255,2,90,0,16,163,255,10,159,0,2,4,207,255,2,185,0,17,8,162,255,8,160,7,0,2,116,255,2,246,35,0,3,60,161,221,245,246,222,163,63,0,8,63,163,222,246,246,222,162,62,0,3,31,244,255,2,121,0,2,7,159,255,8,162,8,0,17,181,255,2,211,5,0,2,160,255,10,162,0,16,86,255,2,254,58,0,2,63,255,3,251,110,16,15,109,252,255,3,64,0,14,15,230,255,2,152,0,3,164,255,3,145,0,4,145,255,3,164,0,14,151,255,2,231,16,0,3,223,255,3,47,0,4,48,255,3,222,0,13,57,254,255,2,87,0,4,247,255,3,14,0,4,14,255,3,246,0,12,5,211,255,2,182,0,5,246,255,3,14,0,4,15,255,3,245,0,12,121,255,2,245,32,0,5,221,255,3,47,0,4,47,255,3,220,0,11,34,246,255,2,117,0,6,161,255,3,144,0,4,141,255,3,161,0,11,185,255,2,208,4,0,6,60,255,3,251,107,15,14,103,250,255,3,59,0,10,91,255,2,253,55,0,8,159,255,10,158,0,10,17,233,255,2,148,0,9,7,159,255,8,160,7,0,10,156,255,2,229,14,0,11,60,161,221,246,246,222,163,62,0,255,0,73,
|
||||
43,31,0,255,0,2,32,124,187,229,246,251,241,218,186,142,91,30,0,17,6,143,251,255,11,0,16,3,187,255,13,0,16,112,255,14,0,16,209,255,5,186,52,10,14,44,107,197,255,2,0,16,246,255,5,22,0,6,50,187,0,16,239,255,5,43,0,24,179,255,5,184,1,0,23,59,254,255,5,147,0,23,36,228,255,6,146,0,21,86,244,255,8,150,1,0,6,20,255,4,237,0,6,109,254,255,10,155,1,0,5,63,255,4,201,0,5,81,255,13,159,2,0,4,145,255,4,164,0,4,15,235,255,4,241,84,209,255,7,164,3,0,2,21,238,255,4,102,0,4,115,255,5,105,0,1,19,206,255,7,168,4,1,172,255,5,28,0,4,194,255,5,24,0,2,17,204,255,7,172,155,255,5,199,0,5,238,255,5,5,0,3,15,201,255,13,78,0,5,251,255,5,38,0,4,14,198,255,11,202,1,0,5,231,255,5,136,0,5,12,194,255,9,242,37,0,6,190,255,5,250,72,0,5,11,191,255,8,142,0,7,108,255,6,251,131,22,0,2,1,65,200,255,8,244,37,0,6,11,226,255,7,253,224,215,242,255,11,202,4,0,6,67,249,255,22,133,0,7,76,242,255,15,229,227,255,4,253,61,0,7,31,178,254,255,10,249,186,87,4,53,251,255,4,224,15,0,8,36,124,183,224,242,251,238,220,182,137,81,13,0,4,123,255,5,165,0,255,0,25,
|
||||
43,11,0,91,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,7,255,4,0,255,0,24,
|
||||
43,16,0,119,20,238,255,4,183,0,9,155,255,4,252,42,0,8,45,253,255,4,157,0,9,177,255,4,251,34,0,8,48,255,5,165,0,9,163,255,5,57,0,8,21,250,255,4,211,0,9,111,255,5,121,0,9,199,255,5,38,0,8,20,253,255,4,223,0,9,85,255,5,160,0,9,139,255,5,109,0,9,184,255,5,66,0,9,217,255,5,36,0,9,240,255,5,15,0,9,251,255,5,4,0,9,251,255,5,4,0,9,240,255,5,14,0,9,219,255,5,36,0,9,186,255,5,66,0,9,141,255,5,109,0,9,88,255,5,159,0,9,23,254,255,4,221,0,10,203,255,5,35,0,9,114,255,5,118,0,9,23,251,255,4,208,0,10,165,255,5,54,0,9,50,255,5,163,0,10,178,255,4,250,33,0,9,46,254,255,4,155,0,10,156,255,4,251,41,0,9,21,238,255,4,183,0,66,
|
||||
43,16,0,114,184,255,4,238,20,0,9,43,252,255,4,153,0,10,157,255,4,253,44,0,9,34,251,255,4,176,0,10,166,255,5,48,0,9,58,255,5,162,0,10,211,255,4,249,20,0,9,122,255,5,109,0,9,39,255,5,198,0,10,224,255,4,253,19,0,9,161,255,5,84,0,9,110,255,5,138,0,9,67,255,5,183,0,9,37,255,5,216,0,9,15,255,5,238,0,9,5,255,5,249,0,9,6,255,5,250,0,9,15,255,5,239,0,9,38,255,5,217,0,9,68,255,5,184,0,9,111,255,5,139,0,9,162,255,5,85,0,9,225,255,4,253,20,0,8,40,255,5,198,0,9,123,255,5,110,0,9,212,255,4,250,21,0,8,59,255,5,162,0,9,167,255,5,48,0,8,35,251,255,4,176,0,9,158,255,4,253,45,0,8,43,252,255,4,154,0,9,184,255,4,238,20,0,71,
|
||||
43,19,0,160,255,3,0,16,255,3,0,16,255,3,0,9,12,198,83,0,4,255,3,0,4,83,198,12,0,2,126,255,2,196,54,0,2,255,3,0,2,54,196,255,2,125,0,2,173,255,3,254,166,31,255,3,31,166,254,255,3,173,0,3,67,201,255,3,247,255,3,248,255,3,204,69,0,6,82,214,255,7,218,87,1,0,8,8,189,255,5,199,11,0,8,1,86,218,255,7,223,91,1,0,5,69,204,255,3,245,255,3,245,255,3,207,71,0,3,173,255,3,254,161,27,255,3,27,161,254,255,3,174,0,2,126,255,2,193,51,0,2,255,3,0,2,51,193,255,2,125,0,2,12,199,82,0,4,255,3,0,4,83,198,12,0,9,255,3,0,16,255,3,0,16,255,3,0,255,0,95,
|
||||
43,30,0,255,0,118,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,17,255,22,0,8,255,22,0,8,255,22,0,8,255,22,0,17,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,26,255,4,0,255,0,28,
|
||||
43,14,0,255,0,127,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,7,14,255,5,227,0,7,86,255,5,83,0,7,164,255,4,184,0,7,3,237,255,3,248,36,0,7,63,255,4,130,0,8,140,255,3,222,9,0,8,217,255,3,77,0,63,
|
||||
43,15,0,255,0,62,255,11,0,4,255,11,0,4,255,11,0,4,255,11,0,4,255,11,0,255,0,2,
|
||||
43,14,0,255,0,127,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,130,
|
||||
43,13,0,112,11,247,255,2,216,0,8,81,255,3,138,0,8,159,255,3,60,0,7,2,234,255,2,235,2,0,7,59,255,3,160,0,8,137,255,3,82,0,8,215,255,2,248,11,0,7,36,255,3,181,0,8,115,255,3,103,0,8,193,255,2,254,26,0,7,18,252,255,2,203,0,8,93,255,3,125,0,8,171,255,3,47,0,7,6,242,255,2,224,0,8,71,255,3,147,0,8,149,255,3,68,0,8,226,255,2,240,5,0,7,49,255,3,168,0,8,127,255,3,90,0,8,205,255,2,251,16,0,7,27,255,3,190,0,8,105,255,3,112,0,8,183,255,3,33,0,7,12,248,255,2,211,0,8,83,255,3,133,0,8,161,255,3,55,0,7,3,235,255,2,231,1,0,7,61,255,3,155,0,8,139,255,3,77,0,8,217,255,2,245,9,0,73,
|
||||
43,25,0,208,47,125,193,222,244,245,222,193,125,47,0,13,35,174,255,10,173,34,0,10,62,241,255,12,240,59,0,8,56,246,255,14,245,53,0,6,9,217,255,16,214,8,0,5,123,255,5,254,151,51,12,11,50,148,253,255,5,120,0,4,2,225,255,5,106,0,6,102,255,5,223,2,0,3,68,255,5,208,0,8,207,255,5,66,0,3,127,255,5,122,0,8,122,255,5,125,0,3,181,255,5,65,0,8,65,255,5,179,0,3,217,255,5,31,0,8,32,255,5,216,0,3,233,255,5,12,0,8,14,255,5,232,0,3,248,255,5,3,0,8,4,255,5,247,0,3,248,255,5,4,0,8,5,255,5,248,0,3,233,255,5,13,0,8,14,255,5,232,0,3,218,255,5,33,0,8,34,255,5,216,0,3,182,255,5,67,0,8,68,255,5,180,0,3,128,255,5,125,0,8,126,255,5,126,0,3,69,255,5,211,1,0,6,1,212,255,5,67,0,3,3,226,255,5,109,0,6,109,255,5,224,2,0,4,125,255,5,254,152,51,11,11,50,152,254,255,5,121,0,5,10,219,255,16,216,8,0,6,58,247,255,14,246,55,0,8,64,242,255,12,241,62,0,10,38,177,255,10,177,36,0,13,48,127,194,223,245,245,224,194,127,48,0,232,
|
||||
43,25,0,204,21,63,106,149,191,234,255,6,0,13,255,12,0,13,255,12,0,13,255,12,0,13,255,12,0,13,235,192,149,107,64,21,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,13,255,18,0,7,255,18,0,7,255,18,0,7,255,18,0,7,255,18,0,228,
|
||||
43,25,0,205,1,49,116,165,209,233,248,248,233,208,159,95,12,0,10,48,144,232,255,11,244,123,6,0,8,255,16,196,14,0,7,255,17,183,0,7,255,18,78,0,6,255,3,254,186,109,45,16,7,37,113,233,255,6,170,0,6,255,1,250,150,37,0,7,25,220,255,5,224,0,6,182,39,0,10,78,255,5,248,0,18,12,255,5,241,0,18,21,255,5,222,0,18,90,255,5,183,0,17,14,218,255,5,130,0,16,10,184,255,6,61,0,15,27,199,255,6,207,0,15,75,236,255,6,253,60,0,13,5,141,254,255,7,129,0,13,33,202,255,8,172,2,0,12,84,240,255,8,181,7,0,11,8,151,255,8,251,120,1,0,11,40,209,255,8,225,57,0,12,94,244,255,8,175,17,0,13,255,19,0,6,255,19,0,6,255,19,0,6,255,19,0,6,255,19,0,228,
|
||||
43,25,0,203,28,84,132,172,204,229,244,252,248,237,218,183,138,66,4,0,10,255,14,222,92,0,9,255,16,140,0,8,255,17,76,0,7,255,17,183,0,7,224,161,111,67,38,15,5,4,22,64,149,251,255,5,233,0,18,85,255,5,246,0,18,9,255,5,217,0,18,81,255,5,162,0,14,4,21,60,139,247,255,4,253,46,0,11,255,11,251,89,0,12,255,10,175,39,0,13,255,10,252,171,34,0,12,255,12,240,60,0,11,255,13,236,20,0,13,7,22,54,113,211,255,6,128,0,17,3,158,255,5,205,0,18,23,255,5,242,0,18,21,255,5,248,0,5,201,92,8,0,9,2,155,255,5,222,0,5,255,2,244,172,106,58,24,8,3,17,49,107,207,255,6,165,0,5,255,19,65,0,5,255,18,154,0,6,255,17,150,4,0,6,55,166,248,255,12,198,69,0,10,12,84,148,195,229,246,252,241,229,201,161,110,34,0,233,
|
||||
43,25,0,211,7,212,255,7,0,16,139,255,8,0,15,60,253,255,8,0,14,12,221,255,9,0,14,152,255,3,254,255,6,0,13,72,255,4,143,255,6,0,12,17,229,255,3,215,8,255,6,0,12,165,255,3,251,52,0,1,255,6,0,11,84,255,4,129,0,2,255,6,0,10,23,235,255,3,205,5,0,2,255,6,0,10,179,255,3,248,43,0,3,255,6,0,9,98,255,4,116,0,4,255,6,0,8,31,241,255,3,194,2,0,4,255,6,0,7,1,190,255,3,243,34,0,5,255,6,0,7,111,255,4,102,0,6,255,6,0,7,246,255,3,182,0,7,255,6,0,7,255,22,0,3,255,22,0,3,255,22,0,3,255,22,0,3,255,22,0,15,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,230,
|
||||
43,25,0,204,255,17,0,8,255,17,0,8,255,17,0,8,255,17,0,8,255,17,0,8,255,5,0,20,255,5,0,20,255,5,0,20,255,5,163,214,239,251,237,219,175,120,35,0,11,255,13,254,181,34,0,9,255,15,244,79,0,8,255,16,248,64,0,7,255,17,219,6,0,6,255,2,238,158,93,40,15,4,21,66,150,249,255,6,94,0,6,199,86,5,0,8,45,232,255,5,172,0,18,89,255,5,221,0,18,14,255,5,244,0,18,14,255,5,244,0,18,89,255,5,220,0,5,206,106,17,0,9,43,232,255,5,168,0,5,255,2,251,193,123,74,32,12,3,19,63,146,248,255,6,86,0,5,255,18,206,2,0,5,255,17,239,47,0,6,255,16,230,54,0,7,52,155,242,255,11,246,150,16,0,10,6,66,133,178,217,237,250,247,231,207,158,100,15,0,232,
|
||||
43,25,0,209,55,128,193,220,241,249,231,192,134,47,0,13,64,200,255,10,199,67,0,9,1,137,255,14,0,9,163,255,15,0,8,112,255,16,0,7,41,249,255,5,232,131,60,20,5,15,47,110,201,255,2,0,7,158,255,5,177,13,0,8,53,188,0,6,22,248,255,4,212,7,0,17,92,255,5,92,14,111,185,232,250,240,218,165,92,6,0,8,151,255,5,119,239,255,8,228,81,0,7,202,255,17,128,0,6,224,255,18,99,0,5,242,255,18,239,18,0,4,251,255,7,179,58,18,9,51,164,255,6,118,0,4,238,255,6,179,0,6,179,255,5,192,0,4,222,255,6,58,0,6,58,255,5,230,0,4,193,255,6,18,0,6,18,255,5,249,0,4,141,255,6,18,0,6,18,255,5,236,0,4,84,255,6,58,0,6,58,255,5,210,0,4,10,239,255,5,179,0,6,179,255,5,147,0,5,145,255,6,178,57,17,8,51,164,255,6,63,0,5,21,234,255,16,187,0,7,80,254,255,14,232,33,0,8,90,250,255,12,228,50,0,10,55,198,255,9,252,165,20,0,13,64,141,203,229,249,243,224,184,121,33,0,232,
|
||||
43,25,0,202,255,20,0,5,255,20,0,5,255,20,0,5,255,19,253,0,5,255,19,169,0,17,108,255,6,50,0,16,3,223,255,5,187,0,17,90,255,6,68,0,17,208,255,5,205,0,17,73,255,6,86,0,17,192,255,5,219,2,0,16,55,255,6,103,0,17,174,255,5,232,8,0,16,40,253,255,5,121,0,17,157,255,5,242,16,0,16,26,249,255,5,138,0,17,139,255,5,249,26,0,16,16,242,255,5,156,0,17,122,255,5,253,39,0,16,8,232,255,5,174,0,17,104,255,6,55,0,16,3,220,255,5,191,0,17,87,255,6,72,0,17,205,255,5,208,0,17,69,255,6,90,0,17,188,255,5,223,4,0,237,
|
||||
43,25,0,206,6,73,149,194,229,243,252,243,229,194,149,73,5,0,11,86,225,255,11,223,83,0,9,121,255,15,119,0,7,58,253,255,15,253,57,0,6,167,255,17,166,0,6,228,255,5,234,101,28,7,27,97,232,255,5,227,0,6,250,255,5,70,0,5,69,255,5,249,0,6,239,255,5,13,0,5,13,255,5,238,0,6,191,255,5,69,0,5,70,255,5,189,0,6,94,255,5,232,98,27,6,27,97,232,255,5,91,0,6,2,181,255,15,165,1,0,7,6,143,251,255,11,245,133,2,0,9,18,136,254,255,9,253,129,18,0,9,113,242,255,13,242,113,0,7,142,255,17,142,0,5,68,255,6,158,61,16,4,26,64,164,254,255,5,67,0,4,176,255,5,122,0,7,120,255,5,175,0,4,233,255,5,16,0,7,17,255,5,232,0,4,251,255,5,16,0,7,17,255,5,250,0,4,234,255,5,119,0,7,118,255,5,232,0,4,193,255,5,254,154,59,15,4,24,62,161,254,255,5,192,0,4,109,255,19,109,0,4,8,217,255,17,217,8,0,5,40,225,255,15,226,40,0,7,21,151,251,255,11,252,154,22,0,10,19,98,159,202,231,244,253,244,231,203,161,101,21,0,231,
|
||||
43,25,0,207,34,121,184,223,242,248,227,201,137,61,0,13,20,165,252,255,9,193,50,0,10,50,228,255,12,248,81,0,8,32,232,255,14,252,74,0,7,187,255,16,230,17,0,5,63,255,6,167,52,9,9,53,170,255,6,140,0,5,147,255,5,181,0,6,170,255,5,237,8,0,4,210,255,5,58,0,6,53,255,6,82,0,4,237,255,5,18,0,6,9,255,6,138,0,4,250,255,5,18,0,6,9,255,6,191,0,4,232,255,5,58,0,6,52,255,6,220,0,4,194,255,5,179,0,6,167,255,6,237,0,4,121,255,6,179,58,18,18,58,181,255,7,251,0,4,21,242,255,18,241,0,5,106,255,18,223,0,6,136,255,17,201,0,7,88,231,255,8,236,115,255,5,150,0,8,7,95,167,220,241,250,232,185,108,11,99,255,5,90,0,17,10,218,255,4,248,21,0,6,186,50,0,8,17,185,255,5,156,0,7,255,2,195,106,44,13,4,20,61,134,235,255,5,248,40,0,7,255,16,110,0,8,255,15,162,0,9,255,14,135,1,0,9,69,203,255,10,198,63,0,13,53,138,196,234,250,241,220,192,127,54,0,234,
|
||||
43,14,0,200,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,92,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,130,
|
||||
43,14,0,200,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,92,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,8,255,6,0,7,14,255,5,227,0,7,86,255,5,83,0,7,164,255,4,184,0,7,3,237,255,3,248,36,0,7,63,255,4,130,0,8,140,255,3,222,9,0,8,217,255,3,77,0,63,
|
||||
43,30,0,255,0,129,34,122,211,0,24,26,112,201,255,3,0,21,19,102,191,253,255,5,0,18,13,92,181,250,255,8,0,15,8,82,171,246,255,9,203,118,0,12,4,72,161,241,255,9,201,116,32,0,11,1,62,151,235,255,8,254,199,114,30,0,12,52,140,227,255,8,254,197,112,28,0,15,255,8,253,195,110,27,0,18,255,5,253,193,108,25,0,21,255,5,251,184,100,20,0,21,255,8,252,188,103,22,0,18,52,141,228,255,8,252,191,107,25,0,17,1,63,152,235,255,8,253,195,111,28,0,17,4,73,162,241,255,8,254,198,114,30,0,17,8,83,172,246,255,9,202,118,0,18,13,93,182,250,255,8,0,21,19,103,192,253,255,5,0,24,26,113,202,255,3,0,27,35,123,212,0,255,0,78,
|
||||
43,30,0,255,0,255,0,4,255,23,0,7,255,23,0,7,255,23,0,7,255,23,0,127,255,23,0,7,255,23,0,7,255,23,0,7,255,23,0,255,0,168,
|
||||
43,30,0,255,0,109,211,122,34,0,27,255,3,200,112,26,0,24,255,5,253,190,102,19,0,21,255,8,250,180,92,13,0,18,118,203,255,9,246,170,82,8,0,17,32,116,201,255,9,241,160,72,4,0,17,30,114,199,254,255,8,235,150,62,1,0,17,28,112,196,254,255,8,227,140,52,0,18,26,110,194,253,255,8,0,21,24,107,192,253,255,5,0,21,19,99,183,250,255,5,0,18,22,103,187,251,255,8,0,15,25,107,191,252,255,8,228,141,52,0,12,27,110,194,253,255,8,235,151,63,1,0,11,31,114,198,254,255,8,241,161,73,4,0,12,118,202,255,9,246,171,83,8,0,15,255,8,250,181,93,13,0,18,255,5,253,191,103,19,0,21,255,3,201,113,26,0,24,212,123,34,0,255,0,98,
|
||||
43,21,0,170,28,84,133,175,209,235,248,251,238,216,171,103,18,0,8,255,12,242,114,0,7,255,14,145,0,6,255,15,67,0,5,255,15,171,0,5,255,2,223,136,72,26,6,23,88,227,255,5,229,0,5,194,71,1,0,6,59,255,5,249,0,14,12,255,5,231,0,14,85,255,5,181,0,13,36,233,255,5,82,0,12,53,232,255,5,180,0,12,80,246,255,5,209,17,0,11,87,252,255,5,206,23,0,11,51,249,255,5,179,10,0,12,174,255,5,183,4,0,13,236,255,5,38,0,14,255,6,1,0,77,255,6,0,15,255,6,0,15,255,6,0,15,255,6,0,15,255,6,0,15,255,6,0,198,
|
||||
43,36,0,255,0,45,19,97,161,207,238,251,246,233,201,159,94,22,0,22,37,166,250,255,10,250,171,50,0,18,18,154,251,255,14,254,158,14,0,15,43,220,255,4,204,123,68,28,11,5,21,58,116,195,255,4,221,40,0,13,70,242,255,3,179,46,0,10,44,176,255,3,235,46,0,11,42,242,255,2,237,77,0,14,86,243,255,2,226,24,0,9,17,220,255,2,224,34,0,16,52,239,255,2,181,0,9,154,255,2,236,33,0,18,67,253,255,2,88,0,7,37,251,255,2,73,0,5,41,155,224,248,231,173,57,0,1,255,4,0,3,143,255,2,210,0,7,167,255,2,170,0,5,101,250,255,5,252,93,255,4,0,3,14,243,255,2,62,0,5,20,251,255,2,43,0,4,81,254,255,7,243,255,4,0,4,153,255,2,135,0,5,97,255,2,195,0,4,12,234,255,3,188,45,7,49,194,255,5,0,4,83,255,2,195,0,5,160,255,2,117,0,4,104,255,3,220,8,0,3,11,225,255,4,0,4,31,255,2,227,0,5,205,255,2,61,0,4,179,255,3,107,0,5,111,255,4,0,4,11,255,2,246,0,5,237,255,2,22,0,4,228,255,3,42,0,5,45,255,4,0,4,7,255,2,244,0,5,250,255,2,6,0,4,247,255,3,13,0,5,14,255,4,0,4,28,255,2,222,0,5,250,255,2,11,0,4,248,255,3,14,0,5,16,255,4,0,4,78,255,2,187,0,5,238,255,2,34,0,4,229,255,3,43,0,5,45,255,4,0,4,164,255,2,118,0,5,208,255,2,61,0,4,181,255,3,109,0,5,113,255,4,0,3,46,252,255,1,250,33,0,5,164,255,2,125,0,4,107,255,3,220,8,0,3,10,224,255,4,0,2,29,220,255,2,149,0,6,105,255,2,198,0,4,13,237,255,3,187,45,6,47,192,255,5,30,115,236,255,2,208,13,0,6,27,253,255,1,253,41,0,4,87,255,8,240,255,8,206,26,0,8,184,255,2,171,0,5,107,251,255,5,251,89,255,6,242,133,6,0,9,66,255,2,254,64,0,5,44,158,225,249,232,174,56,0,1,255,2,250,223,168,103,14,0,12,178,255,2,234,30,0,12,23,12,0,17,27,235,255,2,210,28,0,31,67,249,255,2,231,57,0,13,15,165,91,0,15,81,248,255,2,252,158,29,0,9,10,107,227,255,1,241,32,0,15,64,234,255,3,249,185,109,52,28,6,18,41,91,161,236,255,4,188,0,16,25,174,255,16,176,32,0,18,63,184,253,255,10,248,165,59,0,22,27,105,166,209,239,251,245,225,201,147,86,18,0,120,
|
||||
43,28,0,233,77,255,8,76,0,18,174,255,8,173,0,17,21,250,255,8,250,20,0,16,113,255,10,112,0,16,210,255,10,209,0,15,52,255,12,51,0,14,149,255,5,214,214,255,5,148,0,13,8,238,255,5,117,118,255,5,238,7,0,12,88,255,5,252,24,25,252,255,5,87,0,12,185,255,5,179,0,2,180,255,5,184,0,11,29,253,255,5,81,0,2,82,255,5,253,28,0,10,124,255,5,235,5,0,2,5,235,255,5,123,0,10,220,255,5,143,0,4,144,255,5,219,0,9,63,255,6,46,0,4,47,255,6,62,0,8,160,255,5,205,0,6,206,255,5,159,0,7,13,244,255,5,108,0,6,109,255,5,244,12,0,6,99,255,20,98,0,6,196,255,20,195,0,5,38,255,22,37,0,4,135,255,22,134,0,3,3,229,255,22,228,3,0,2,74,255,6,36,0,10,36,255,6,73,0,2,171,255,5,193,0,12,194,255,5,170,0,1,19,249,255,5,95,0,12,96,255,5,248,18,110,255,5,242,11,0,12,11,243,255,5,109,207,255,5,156,0,14,157,255,5,207,0,252,
|
||||
43,27,0,219,255,10,253,244,233,209,174,126,55,1,0,9,255,17,211,74,0,8,255,18,254,108,0,7,255,19,250,46,0,6,255,20,151,0,6,255,6,0,5,16,43,123,240,255,5,218,0,6,255,6,0,8,69,255,5,244,0,6,255,6,0,8,7,255,5,239,0,6,255,6,0,8,67,255,5,208,0,6,255,6,0,5,15,42,120,238,255,5,125,0,6,255,19,226,20,0,6,255,18,213,44,0,7,255,18,143,17,0,7,255,19,228,41,0,6,255,20,218,7,0,5,255,6,0,5,4,21,67,159,255,6,104,0,5,255,6,0,9,119,255,5,189,0,5,255,6,0,9,16,255,5,235,0,5,255,6,0,9,17,255,5,251,0,5,255,6,0,9,122,255,5,235,0,5,255,6,0,5,4,21,67,161,255,6,200,0,5,255,21,122,0,5,255,20,231,16,0,5,255,19,240,60,0,6,255,18,180,38,0,7,255,12,248,236,213,171,117,36,0,249,
|
||||
43,26,0,218,47,110,171,209,228,246,248,233,205,158,99,21,0,11,3,86,203,255,11,253,179,62,0,8,30,197,255,16,0,7,62,237,255,17,0,6,41,239,255,18,0,5,9,221,255,6,252,167,88,33,12,6,21,47,95,155,234,255,2,0,5,118,255,6,211,41,0,9,3,80,197,0,4,11,237,255,5,209,12,0,17,77,255,5,251,37,0,18,149,255,5,162,0,19,202,255,5,83,0,19,224,255,5,30,0,19,245,255,5,9,0,19,246,255,5,8,0,19,225,255,5,29,0,19,203,255,5,81,0,19,150,255,5,161,0,19,78,255,5,251,36,0,18,11,238,255,5,207,11,0,18,119,255,6,208,38,0,9,3,79,197,0,5,9,222,255,6,252,166,86,32,11,5,20,46,94,155,234,255,2,0,6,42,239,255,18,0,7,63,237,255,17,0,8,30,198,255,16,0,9,3,87,204,255,11,253,180,63,0,12,48,111,172,210,229,247,249,234,206,159,99,22,0,238,
|
||||
43,30,0,243,255,7,250,245,239,224,208,184,152,111,57,4,0,13,255,16,235,147,34,0,11,255,18,251,136,7,0,9,255,20,202,25,0,8,255,21,216,21,0,7,255,6,0,3,9,23,48,96,157,241,255,7,192,2,0,6,255,6,0,8,9,124,247,255,6,104,0,6,255,6,0,10,52,239,255,5,228,5,0,5,255,6,0,11,71,255,6,66,0,5,255,6,0,12,180,255,5,141,0,5,255,6,0,12,92,255,5,199,0,5,255,6,0,12,34,255,5,223,0,5,255,6,0,12,11,255,5,245,0,5,255,6,0,12,12,255,5,244,0,5,255,6,0,12,36,255,5,222,0,5,255,6,0,12,95,255,5,198,0,5,255,6,0,12,184,255,5,140,0,5,255,6,0,11,75,255,6,66,0,5,255,6,0,10,55,241,255,5,228,5,0,5,255,6,0,8,10,126,248,255,6,104,0,6,255,6,0,3,8,22,47,95,158,242,255,7,192,2,0,6,255,21,217,22,0,7,255,20,202,25,0,8,255,18,250,135,7,0,9,255,16,234,145,32,0,11,255,7,252,247,240,225,208,183,152,110,55,3,0,255,0,25,
|
||||
43,25,0,203,255,19,0,6,255,19,0,6,255,19,0,6,255,19,0,6,255,19,0,6,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,18,0,7,255,18,0,7,255,18,0,7,255,18,0,7,255,18,0,7,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,19,0,6,255,19,0,6,255,19,0,6,255,19,0,6,255,19,0,228,
|
||||
43,25,0,203,255,18,0,7,255,18,0,7,255,18,0,7,255,18,0,7,255,18,0,7,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,17,0,8,255,17,0,8,255,17,0,8,255,17,0,8,255,17,0,8,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,241,
|
||||
43,30,0,250,29,92,151,200,220,237,251,243,230,206,166,124,59,4,0,14,66,178,254,255,12,241,155,54,0,10,18,174,255,18,0,9,48,228,255,19,0,8,32,231,255,20,0,7,5,214,255,7,198,110,53,23,6,10,24,48,90,137,205,254,255,2,0,7,110,255,6,223,63,0,11,21,110,207,0,6,9,235,255,5,217,19,0,21,74,255,5,252,43,0,22,147,255,5,165,0,23,201,255,5,84,0,23,224,255,5,30,0,8,255,10,0,5,245,255,5,10,0,8,255,10,0,5,245,255,5,9,0,8,255,10,0,5,224,255,5,31,0,8,255,10,0,5,202,255,5,85,0,8,255,10,0,5,148,255,5,168,0,12,255,6,0,5,76,255,5,253,48,0,11,255,6,0,5,10,236,255,5,222,24,0,10,255,6,0,6,114,255,6,228,72,0,9,255,6,0,6,7,218,255,7,205,115,59,24,8,5,18,45,97,255,6,0,7,37,235,255,21,0,8,55,233,255,20,0,9,24,187,255,17,253,179,0,10,1,79,194,255,13,221,140,35,0,14,40,104,165,207,226,245,251,238,224,194,151,107,41,0,255,0,22,
|
||||
43,30,0,243,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,24,0,6,255,24,0,6,255,24,0,6,255,24,0,6,255,24,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,6,255,6,0,12,255,6,0,255,0,18,
|
||||
43,13,0,107,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,121,
|
||||
43,15,0,125,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,9,255,6,0,8,2,255,5,253,0,8,22,255,5,237,0,8,79,255,5,217,0,7,4,198,255,5,167,0,5,9,60,189,255,6,104,0,4,255,9,240,13,0,4,255,9,115,0,5,255,8,162,0,6,255,6,239,112,0,7,255,1,252,236,215,165,101,12,0,38,
|
||||
43,29,0,235,255,6,0,9,38,223,255,6,254,115,0,4,255,6,0,8,54,235,255,6,250,91,0,5,255,6,0,7,73,244,255,6,243,70,0,6,255,6,0,6,95,251,255,6,234,52,0,7,255,6,0,5,120,255,7,222,37,0,8,255,6,0,3,1,145,255,7,207,24,0,9,255,6,0,2,6,168,255,7,190,14,0,10,255,6,0,1,14,189,255,7,170,6,0,11,255,6,24,207,255,7,147,2,0,12,255,6,222,255,7,122,0,14,255,12,251,97,0,15,255,11,245,76,0,16,255,11,169,1,0,16,255,12,157,3,0,15,255,13,171,6,0,14,255,6,248,255,7,184,10,0,13,255,6,66,243,255,7,197,16,0,12,255,6,0,1,53,236,255,7,208,23,0,11,255,6,0,2,41,227,255,7,218,31,0,10,255,6,0,3,31,217,255,7,227,40,0,9,255,6,0,4,22,206,255,7,234,50,0,8,255,6,0,5,14,193,255,7,241,61,0,7,255,6,0,6,8,178,255,7,246,74,0,6,255,6,0,7,4,162,255,7,250,88,0,5,255,6,0,8,1,145,255,7,253,103,0,4,255,6,0,10,127,255,8,119,0,255,0,6,
|
||||
43,23,0,187,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,6,0,17,255,19,0,4,255,19,0,4,255,19,0,4,255,19,0,4,255,19,0,208,
|
||||
43,36,0,255,0,36,255,7,121,0,13,121,255,7,0,7,255,7,229,5,0,11,6,230,255,7,0,7,255,8,94,0,11,95,255,8,0,7,255,8,208,0,11,209,255,8,0,7,255,9,68,0,9,69,255,9,0,7,255,9,183,0,9,184,255,9,0,7,255,10,43,0,7,44,255,10,0,7,255,6,197,255,3,157,0,7,158,255,3,196,255,6,0,7,255,6,82,255,3,248,23,0,5,23,248,255,3,81,255,6,0,7,255,6,2,221,255,3,130,0,5,131,255,3,220,2,255,6,0,7,255,6,0,1,109,255,3,235,9,0,3,9,236,255,3,108,0,1,255,6,0,7,255,6,0,1,11,238,255,3,104,0,3,105,255,3,238,11,0,1,255,6,0,7,255,6,0,2,135,255,3,217,1,0,1,2,218,255,3,134,0,2,255,6,0,7,255,6,0,2,26,250,255,3,78,0,1,79,255,3,250,26,0,2,255,6,0,7,255,6,0,3,162,255,3,193,0,1,194,255,3,161,0,3,255,6,0,7,255,6,0,3,47,255,4,105,255,4,47,0,3,255,6,0,7,255,6,0,4,188,255,3,253,255,3,187,0,4,255,6,0,7,255,6,0,4,74,255,7,73,0,4,255,6,0,7,255,6,0,4,1,214,255,5,213,1,0,4,255,6,0,7,255,6,0,5,100,255,5,99,0,5,255,6,0,7,255,6,0,5,8,233,255,3,233,7,0,5,255,6,0,7,255,6,0,17,255,6,0,7,255,6,0,17,255,6,0,7,255,6,0,17,255,6,0,7,255,6,0,17,255,6,0,7,255,6,0,17,255,6,0,255,0,73,
|
||||
43,30,0,243,255,7,139,0,10,255,6,0,6,255,7,246,26,0,9,255,6,0,6,255,8,152,0,9,255,6,0,6,255,8,251,35,0,8,255,6,0,6,255,9,165,0,8,255,6,0,6,255,9,254,46,0,7,255,6,0,6,255,6,207,255,3,179,0,7,255,6,0,6,255,6,71,255,4,57,0,6,255,6,0,6,255,6,0,1,188,255,3,192,0,6,255,6,0,6,255,6,0,1,51,254,255,3,71,0,5,255,6,0,6,255,6,0,2,168,255,3,204,1,0,4,255,6,0,6,255,6,0,2,35,250,255,3,84,0,4,255,6,0,6,255,6,0,3,147,255,3,215,3,0,3,255,6,0,6,255,6,0,3,22,242,255,3,97,0,3,255,6,0,6,255,6,0,4,127,255,3,225,7,0,2,255,6,0,6,255,6,0,4,12,232,255,3,111,0,2,255,6,0,6,255,6,0,5,106,255,3,233,12,0,1,255,6,0,6,255,6,0,5,4,219,255,3,124,0,1,255,6,0,6,255,6,0,6,85,255,3,240,18,255,6,0,6,255,6,0,7,202,255,3,137,255,6,0,6,255,6,0,7,65,255,3,246,255,6,0,6,255,6,0,8,183,255,9,0,6,255,6,0,8,46,253,255,8,0,6,255,6,0,9,162,255,8,0,6,255,6,0,9,31,248,255,7,0,6,255,6,0,10,141,255,7,0,255,0,18,
|
||||
43,31,0,255,0,2,9,73,136,193,218,236,251,236,218,194,136,73,10,0,16,17,125,235,255,11,235,125,17,0,13,63,231,255,15,231,62,0,11,101,252,255,17,251,101,0,9,71,252,255,19,252,69,0,7,23,240,255,6,232,126,55,20,5,21,56,127,233,255,6,239,22,0,6,142,255,6,163,10,0,7,11,167,255,6,141,0,5,19,246,255,5,169,0,10,1,173,255,5,246,19,0,4,89,255,5,240,16,0,11,17,242,255,5,87,0,4,156,255,5,143,0,13,145,255,5,154,0,4,206,255,5,73,0,13,75,255,5,204,0,4,226,255,5,26,0,13,28,255,5,225,0,4,246,255,5,8,0,13,10,255,5,245,0,4,246,255,5,8,0,13,8,255,5,246,0,4,227,255,5,26,0,13,27,255,5,225,0,4,206,255,5,72,0,13,74,255,5,205,0,4,158,255,5,142,0,13,144,255,5,156,0,4,90,255,5,239,14,0,11,16,241,255,5,88,0,4,20,247,255,5,166,0,11,170,255,5,247,20,0,5,144,255,6,160,9,0,7,10,164,255,6,143,0,6,24,241,255,6,230,124,54,19,4,19,55,125,232,255,6,240,23,0,7,74,253,255,19,252,73,0,9,105,252,255,17,252,104,0,11,66,233,255,15,233,66,0,13,18,128,236,255,11,236,128,19,0,16,10,75,138,195,219,238,251,238,220,195,138,75,10,0,255,0,33,
|
||||
43,26,0,211,255,12,243,227,195,144,73,2,0,8,255,17,225,85,0,7,255,19,152,1,0,5,255,20,129,0,5,255,20,249,35,0,4,255,6,0,5,9,38,101,213,255,6,132,0,4,255,6,0,8,7,184,255,5,202,0,4,255,6,0,9,44,255,5,233,0,4,255,6,0,9,7,255,5,250,0,4,255,6,0,9,45,255,5,233,0,4,255,6,0,8,7,185,255,5,202,0,4,255,6,0,5,8,37,100,213,255,6,131,0,4,255,20,249,35,0,4,255,20,129,0,5,255,19,152,1,0,5,255,17,226,87,0,7,255,12,244,229,197,146,73,2,0,8,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,251,
|
||||
43,31,0,255,0,2,9,73,136,193,218,236,251,237,219,195,139,78,12,0,16,17,125,235,255,11,239,134,23,0,13,63,231,255,15,238,75,0,11,101,252,255,17,254,118,0,9,71,252,255,19,254,85,0,7,23,240,255,6,232,126,55,20,5,21,56,127,233,255,6,246,30,0,6,142,255,6,163,10,0,7,11,167,255,6,153,0,5,19,246,255,5,169,0,10,1,173,255,5,250,24,0,4,88,255,5,240,16,0,11,17,242,255,5,93,0,4,156,255,5,143,0,13,145,255,5,160,0,4,205,255,5,73,0,13,75,255,5,207,0,4,226,255,5,26,0,13,28,255,5,226,0,4,246,255,5,8,0,13,10,255,5,246,0,4,246,255,5,7,0,13,8,255,5,248,0,4,227,255,5,24,0,13,27,255,5,235,0,4,207,255,5,68,0,13,74,255,5,208,0,4,160,255,5,134,0,13,144,255,5,166,0,4,92,255,5,233,9,0,11,16,241,255,5,104,0,4,22,248,255,5,150,0,11,170,255,5,253,28,0,5,148,255,6,142,5,0,7,10,164,255,6,175,0,6,27,243,255,6,223,117,50,18,4,19,55,125,232,255,6,252,49,0,7,79,253,255,20,136,0,9,108,253,255,18,177,3,0,10,67,233,255,16,156,6,0,12,18,126,233,255,12,229,78,0,16,8,71,132,190,217,235,251,255,6,241,36,0,23,78,253,255,5,207,8,0,23,108,255,6,154,0,24,140,255,6,91,0,23,1,170,255,5,244,40,0,23,8,196,255,5,212,10,0,127,
|
||||
43,28,0,227,255,10,251,240,226,191,147,74,7,0,11,255,16,227,90,0,10,255,18,121,0,9,255,18,252,50,0,8,255,19,154,0,8,255,6,0,3,2,14,49,127,247,255,5,219,0,8,255,6,0,7,93,255,5,244,0,8,255,6,0,7,12,255,5,248,0,8,255,6,0,7,14,255,5,222,0,8,255,6,0,7,97,255,5,162,0,8,255,6,0,3,1,13,49,129,248,255,5,58,0,8,255,18,143,0,9,255,16,248,123,1,0,9,255,15,231,51,0,11,255,16,242,66,0,10,255,17,244,38,0,9,255,6,0,2,7,33,95,208,255,6,186,0,9,255,6,0,5,6,183,255,6,62,0,8,255,6,0,6,19,234,255,5,179,0,8,255,6,0,7,112,255,5,254,37,0,7,255,6,0,7,12,240,255,5,148,0,7,255,6,0,8,140,255,5,244,16,0,6,255,6,0,8,31,252,255,5,117,0,6,255,6,0,9,170,255,5,225,3,0,5,255,6,0,9,57,255,6,86,0,5,255,6,0,10,200,255,5,199,0,254,
|
||||
43,26,0,215,27,115,172,217,237,250,249,239,221,193,160,115,68,13,0,10,21,159,253,255,12,252,203,0,8,34,224,255,16,0,7,5,212,255,17,0,7,101,255,18,0,7,186,255,5,243,127,51,15,3,12,30,72,121,190,250,255,2,0,7,231,255,5,73,0,9,15,103,205,0,7,250,255,5,11,0,19,236,255,5,97,0,19,188,255,5,253,172,91,34,1,0,15,96,255,9,244,206,166,120,59,6,0,10,3,192,255,13,239,155,42,0,9,16,182,255,14,253,143,5,0,8,1,84,204,255,14,164,0,11,40,111,171,219,253,255,10,71,0,14,9,51,106,174,248,255,6,170,0,18,22,195,255,5,226,0,19,40,255,5,248,0,5,193,67,0,12,12,255,5,241,0,5,255,2,199,97,13,0,9,110,255,5,217,0,5,255,4,245,176,117,61,31,11,3,21,67,159,254,255,5,158,0,5,255,20,70,0,5,255,19,181,0,6,255,18,201,15,0,6,62,145,225,255,13,243,126,8,0,10,33,93,144,181,216,235,247,252,241,227,195,151,85,9,0,240,
|
||||
43,25,0,200,255,24,0,1,255,24,0,1,255,24,0,1,255,24,0,1,255,24,0,10,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,235,
|
||||
43,29,0,235,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,255,6,0,11,255,6,0,6,250,255,5,4,0,9,4,255,5,249,0,6,233,255,5,20,0,9,21,255,5,232,0,6,213,255,5,63,0,9,65,255,5,212,0,6,164,255,5,146,0,9,149,255,5,162,0,6,101,255,5,249,57,0,7,60,250,255,5,101,0,6,18,244,255,5,247,139,56,15,3,15,57,141,248,255,5,243,18,0,7,139,255,19,138,0,8,9,205,255,17,203,9,0,9,26,201,255,15,201,26,0,11,5,125,234,255,11,233,125,5,0,14,7,84,144,198,226,241,252,241,225,197,144,84,6,0,255,0,14,
|
||||
43,28,0,224,207,255,5,156,0,14,157,255,5,207,110,255,5,242,10,0,12,11,243,255,5,109,19,249,255,5,94,0,12,95,255,5,249,19,0,1,171,255,5,192,0,12,193,255,5,170,0,2,74,255,5,254,34,0,10,35,254,255,5,73,0,2,3,229,255,5,130,0,10,131,255,5,228,3,0,3,135,255,5,225,2,0,8,2,226,255,5,134,0,4,38,255,6,69,0,8,70,255,6,37,0,5,196,255,5,166,0,8,167,255,5,195,0,6,99,255,5,247,16,0,6,17,247,255,5,98,0,6,13,244,255,5,105,0,6,106,255,5,244,12,0,7,160,255,5,202,0,6,203,255,5,159,0,8,63,255,6,43,0,4,44,255,6,62,0,8,1,220,255,5,141,0,4,142,255,5,220,1,0,9,124,255,5,233,4,0,2,5,234,255,5,123,0,10,29,253,255,5,79,0,2,80,255,5,253,28,0,11,185,255,5,177,0,2,178,255,5,184,0,12,88,255,5,251,23,23,251,255,5,87,0,12,8,238,255,5,115,116,255,5,238,7,0,13,149,255,5,212,213,255,5,148,0,14,52,255,12,51,0,15,210,255,10,209,0,16,113,255,10,112,0,16,21,250,255,8,250,21,0,17,174,255,8,173,0,18,77,255,8,76,0,255,0,6,
|
||||
43,40,0,255,0,66,225,255,5,75,0,8,103,255,6,114,0,8,75,255,5,225,0,2,163,255,5,137,0,8,165,255,6,176,0,8,137,255,5,163,0,2,101,255,5,199,0,8,226,255,6,236,1,0,7,199,255,5,101,0,2,38,255,5,250,10,0,6,32,255,3,245,240,255,3,44,0,6,10,250,255,5,39,0,3,231,255,5,68,0,6,94,255,3,188,181,255,3,105,0,6,66,255,5,233,0,4,170,255,5,130,0,6,156,255,3,127,119,255,3,167,0,6,128,255,5,172,0,4,107,255,5,192,0,6,217,255,3,65,57,255,3,228,0,6,190,255,5,110,0,4,45,255,5,247,7,0,4,23,255,3,250,9,5,246,255,3,35,0,4,5,246,255,5,49,0,4,1,237,255,5,61,0,4,85,255,3,198,0,2,190,255,3,96,0,4,57,255,5,240,2,0,5,176,255,5,123,0,4,146,255,3,137,0,2,128,255,3,158,0,4,119,255,5,181,0,6,114,255,5,185,0,4,208,255,3,76,0,2,66,255,3,220,0,4,181,255,5,120,0,6,52,255,5,243,4,0,2,16,253,255,2,253,16,0,2,10,250,255,3,26,0,2,2,240,255,5,58,0,6,3,242,255,5,54,0,2,75,255,3,209,0,4,199,255,3,87,0,2,48,255,5,246,6,0,7,183,255,5,116,0,2,137,255,3,147,0,4,137,255,3,149,0,2,110,255,5,191,0,8,121,255,5,178,0,2,199,255,3,86,0,4,75,255,3,211,0,2,172,255,5,129,0,8,59,255,5,238,2,9,250,255,3,24,0,4,15,253,255,2,254,18,0,1,233,255,5,67,0,8,6,246,255,5,47,66,255,3,219,0,6,207,255,3,79,40,255,5,250,10,0,9,190,255,5,109,128,255,3,157,0,6,146,255,3,140,101,255,5,200,0,10,128,255,5,171,189,255,3,96,0,6,84,255,3,202,163,255,5,138,0,10,65,255,5,234,245,255,3,35,0,6,22,255,3,251,230,255,5,76,0,10,9,249,255,8,229,0,8,216,255,8,253,17,0,11,197,255,8,168,0,8,154,255,8,209,0,12,134,255,8,106,0,8,93,255,8,147,0,12,72,255,8,45,0,8,31,255,8,86,0,12,13,252,255,6,237,1,0,9,225,255,7,24,0,13,203,255,6,178,0,10,163,255,6,218,0,255,0,112,
|
||||
43,28,0,225,167,255,6,168,0,10,169,255,6,166,0,2,17,228,255,6,91,0,8,92,255,6,227,16,0,3,68,254,255,5,240,29,0,6,30,240,255,5,254,67,0,5,144,255,6,190,1,0,4,2,191,255,6,143,0,6,8,213,255,6,115,0,4,116,255,6,212,8,0,7,48,250,255,5,248,44,0,2,45,248,255,5,249,48,0,9,121,255,6,209,6,6,209,255,6,120,0,10,2,195,255,6,138,139,255,6,195,2,0,11,33,242,255,5,253,253,255,5,242,32,0,13,97,255,12,96,0,15,174,255,10,174,0,16,20,232,255,8,231,20,0,17,86,255,8,86,0,18,163,255,8,162,0,17,78,255,10,78,0,15,18,231,255,10,231,18,0,14,165,255,12,164,0,13,80,255,6,218,219,255,6,79,0,11,19,232,255,5,253,60,60,253,255,5,231,18,0,10,167,255,6,142,0,2,143,255,6,166,0,9,82,255,6,217,9,0,2,9,218,255,6,81,0,7,20,233,255,5,253,57,0,4,60,253,255,5,232,19,0,6,169,255,6,139,0,6,142,255,6,168,0,5,84,255,6,215,8,0,6,9,218,255,6,83,0,3,21,234,255,5,252,55,0,8,59,253,255,5,233,20,0,2,170,255,6,137,0,10,141,255,6,170,0,253,
|
||||
43,26,0,208,171,255,6,136,0,10,137,255,6,170,21,235,255,5,252,53,0,8,54,252,255,5,234,21,0,1,87,255,6,212,6,0,6,7,213,255,6,86,0,3,173,255,6,134,0,6,135,255,6,172,0,4,22,236,255,5,251,51,0,4,52,252,255,5,235,22,0,5,89,255,6,211,6,0,2,6,212,255,6,88,0,7,175,255,6,132,0,2,133,255,6,174,0,8,23,236,255,5,251,50,51,251,255,5,236,23,0,9,90,255,6,210,210,255,6,89,0,11,176,255,12,175,0,12,24,237,255,10,237,23,0,13,92,255,10,91,0,15,178,255,8,177,0,16,25,238,255,6,238,24,0,17,93,255,6,92,0,19,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,244,
|
||||
43,26,0,210,255,23,0,3,255,23,0,3,255,23,0,3,255,23,0,3,255,22,163,0,16,50,245,255,6,195,6,0,15,27,229,255,6,221,20,0,15,10,205,255,6,239,40,0,15,1,174,255,6,251,67,0,16,136,255,7,101,0,16,95,255,7,140,0,16,61,249,255,6,177,2,0,15,34,235,255,6,206,11,0,15,15,214,255,6,229,27,0,15,4,186,255,6,245,50,0,16,150,255,6,253,80,0,16,110,255,7,117,0,16,73,252,255,6,155,0,16,43,241,255,6,189,5,0,15,22,223,255,6,216,17,0,15,7,197,255,6,236,36,0,16,164,255,22,0,3,255,23,0,3,255,23,0,3,255,23,0,3,255,23,0,235,
|
||||
43,16,0,115,255,11,0,5,255,11,0,5,255,11,0,5,255,11,0,5,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,11,0,5,255,11,0,5,255,11,0,5,255,11,0,66,
|
||||
43,13,0,104,217,255,2,245,9,0,8,139,255,3,77,0,8,61,255,3,155,0,8,3,235,255,2,231,1,0,8,161,255,3,55,0,8,83,255,3,133,0,8,12,248,255,2,211,0,9,183,255,3,33,0,8,105,255,3,112,0,8,27,255,3,190,0,9,205,255,2,251,16,0,8,127,255,3,90,0,8,49,255,3,168,0,9,226,255,2,240,5,0,8,149,255,3,68,0,8,71,255,3,147,0,8,6,242,255,2,224,0,9,171,255,3,47,0,8,93,255,3,125,0,8,18,252,255,2,203,0,9,193,255,2,254,26,0,8,115,255,3,103,0,8,37,255,3,181,0,9,215,255,2,248,11,0,8,137,255,3,82,0,8,59,255,3,160,0,8,2,234,255,2,235,2,0,8,159,255,3,60,0,8,81,255,3,138,0,8,11,247,255,2,216,0,65,
|
||||
43,16,0,114,255,11,0,5,255,11,0,5,255,11,0,5,255,11,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,5,255,11,0,5,255,11,0,5,255,11,0,5,255,11,0,67,
|
||||
43,30,0,252,50,241,255,3,241,49,0,22,39,234,255,5,234,39,0,20,30,226,255,7,226,30,0,18,22,217,255,9,217,22,0,16,15,207,255,5,200,255,5,206,15,0,14,9,195,255,4,242,88,0,1,87,242,255,4,195,9,0,12,5,182,255,4,207,37,0,3,36,205,255,4,181,5,0,10,2,168,255,4,151,7,0,5,7,148,255,4,167,2,0,9,153,255,3,241,86,0,9,83,240,255,3,152,0,8,137,255,3,206,36,0,11,33,202,255,3,136,0,255,0,255,0,243,
|
||||
43,18,0,255,0,255,0,192,255,54,0,18,
|
||||
43,18,0,92,137,255,4,95,0,13,154,255,3,242,34,0,12,2,169,255,3,198,3,0,12,5,182,255,3,129,0,13,9,195,255,2,252,59,0,13,15,207,255,2,223,14,0,13,22,217,255,2,164,0,255,0,255,0,54,
|
||||
43,24,0,255,0,85,23,71,119,167,202,228,243,252,247,234,216,173,122,36,0,10,255,14,180,31,0,8,255,15,235,39,0,7,255,16,211,2,0,6,255,2,201,117,64,26,10,4,19,57,138,249,255,5,84,0,6,185,47,0,9,90,255,5,161,0,17,8,255,5,216,0,7,10,80,150,192,226,240,251,255,9,238,0,6,107,234,255,15,253,0,5,147,255,18,0,4,71,255,19,0,4,173,255,5,241,119,44,11,0,3,1,255,6,0,4,228,255,5,72,0,6,25,255,6,0,4,249,255,5,9,0,6,108,255,6,0,4,236,255,5,67,0,5,46,239,255,6,0,4,185,255,5,231,93,25,5,35,122,244,255,7,0,4,85,255,19,0,5,174,255,11,124,255,6,0,5,8,160,255,8,238,99,0,1,255,6,0,7,57,158,219,245,247,226,189,115,21,0,2,255,6,0,218,
|
||||
43,26,0,185,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,2,21,116,194,229,249,232,194,113,14,0,9,255,6,0,1,98,238,255,7,229,73,0,8,255,6,124,255,10,251,84,0,7,255,18,245,38,0,6,255,19,189,0,6,255,7,229,99,26,5,25,96,227,255,6,48,0,5,255,6,234,29,0,5,27,233,255,5,134,0,5,255,6,113,0,7,113,255,5,193,0,5,255,6,38,0,7,38,255,5,228,0,5,255,6,7,0,7,8,255,5,246,0,5,255,6,7,0,7,8,255,5,246,0,5,255,6,38,0,7,38,255,5,228,0,5,255,6,112,0,7,113,255,5,193,0,5,255,6,233,27,0,5,27,233,255,5,134,0,5,255,7,227,98,25,4,24,95,226,255,6,48,0,5,255,19,189,0,6,255,18,245,38,0,6,255,6,125,255,10,251,84,0,7,255,6,0,1,100,240,255,7,230,74,0,8,255,6,0,2,23,120,195,231,250,233,195,114,14,0,240,
|
||||
43,21,0,255,0,46,6,84,147,202,227,245,246,221,164,79,2,0,8,2,114,231,255,9,219,76,0,6,20,192,255,13,0,5,10,200,255,14,0,5,144,255,15,0,4,31,249,255,6,173,74,23,5,19,64,145,243,255,1,0,4,118,255,5,253,93,0,7,20,169,0,4,188,255,5,151,0,14,224,255,5,51,0,14,245,255,5,10,0,14,245,255,5,10,0,14,224,255,5,51,0,14,188,255,5,150,0,14,118,255,5,253,89,0,7,14,163,0,4,31,249,255,6,170,73,21,4,18,58,134,238,255,1,0,5,144,255,15,0,5,10,201,255,14,0,6,20,193,255,13,0,7,2,116,231,255,9,221,77,0,9,6,85,149,204,229,246,247,222,165,80,3,0,192,
|
||||
43,26,0,199,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,9,14,113,193,232,249,230,194,116,21,0,2,255,6,0,8,75,230,255,7,238,98,0,1,255,6,0,7,87,251,255,10,123,255,6,0,6,41,247,255,18,0,6,192,255,19,0,5,50,255,6,227,97,25,5,26,98,228,255,7,0,5,136,255,5,233,27,0,5,27,233,255,6,0,5,195,255,5,112,0,7,113,255,6,0,5,230,255,5,37,0,7,38,255,6,0,5,247,255,5,7,0,7,8,255,6,0,5,247,255,5,7,0,7,8,255,6,0,5,230,255,5,37,0,7,38,255,6,0,5,195,255,5,112,0,7,113,255,6,0,5,136,255,5,233,27,0,5,27,233,255,6,0,5,50,255,6,227,96,24,4,24,97,227,255,7,0,6,193,255,19,0,6,41,247,255,18,0,7,87,251,255,10,125,255,6,0,8,76,231,255,7,240,101,0,1,255,6,0,9,14,114,195,233,250,231,196,120,23,0,2,255,6,0,237,
|
||||
43,24,0,255,0,88,9,92,155,209,231,248,242,221,179,112,24,0,11,3,122,236,255,9,246,140,8,0,8,22,195,255,13,202,25,0,6,10,201,255,15,202,8,0,5,145,255,5,246,129,41,7,14,74,206,255,5,140,0,4,31,249,255,4,252,67,0,5,9,203,255,4,246,24,0,3,118,255,5,146,0,7,69,255,5,112,0,3,188,255,5,60,0,7,11,255,5,179,0,3,225,255,19,221,0,3,246,255,19,242,0,3,246,255,20,0,3,225,255,20,0,3,190,255,5,25,0,17,120,255,5,109,0,17,34,251,255,4,238,45,0,9,15,103,205,0,5,150,255,5,245,137,55,15,3,15,33,75,123,191,251,255,2,0,5,13,206,255,17,0,6,24,198,255,16,0,7,3,120,233,255,14,0,9,6,85,148,202,228,245,253,246,236,216,192,159,122,76,25,0,218,
|
||||
43,16,0,118,29,129,194,233,249,255,5,0,5,90,245,255,9,0,4,49,252,255,10,0,4,163,255,11,0,4,225,255,5,133,19,0,8,249,255,5,12,0,9,255,6,0,7,255,14,0,2,255,14,0,2,255,14,0,2,255,14,0,2,255,14,0,5,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,10,255,6,0,150,
|
||||
43,26,0,255,0,115,11,110,192,232,249,230,196,119,23,0,2,255,6,0,8,67,226,255,7,240,101,0,1,255,6,0,7,78,249,255,10,125,255,6,0,6,35,243,255,18,0,6,186,255,19,0,5,46,255,6,233,103,26,5,27,104,233,255,7,0,5,133,255,5,238,35,0,5,35,239,255,6,0,5,193,255,5,119,0,7,119,255,6,0,5,229,255,5,40,0,7,41,255,6,0,5,247,255,5,8,0,7,9,255,6,0,5,247,255,5,7,0,7,8,255,6,0,5,229,255,5,36,0,7,40,255,6,0,5,192,255,5,108,0,7,118,255,6,0,5,132,255,5,229,23,0,5,33,237,255,6,0,5,45,255,6,224,94,23,4,26,102,232,255,7,0,6,185,255,19,0,6,35,243,255,18,0,7,78,249,255,10,124,255,6,0,8,68,226,255,7,240,100,5,255,5,248,0,9,12,110,193,233,250,231,196,120,23,0,1,26,255,5,227,0,19,79,255,5,198,0,19,183,255,5,129,0,7,189,58,0,9,120,255,5,254,45,0,7,255,2,209,120,61,22,5,10,36,92,193,255,6,160,0,8,255,16,212,19,0,8,255,15,200,24,0,9,255,13,225,110,2,0,10,32,95,146,189,219,241,251,250,236,221,184,133,68,2,0,34,
|
||||
43,26,0,185,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,2,7,96,177,223,247,240,212,147,40,0,9,255,6,0,1,74,222,255,7,252,119,0,8,255,6,112,253,255,10,104,0,7,255,18,244,18,0,6,255,19,111,0,6,255,7,249,133,40,7,26,121,251,255,5,178,0,6,255,6,254,74,0,5,121,255,5,224,0,6,255,6,160,0,6,42,255,5,242,0,6,255,6,67,0,6,14,255,6,0,6,255,6,19,0,6,4,255,6,0,6,255,6,2,0,6,1,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,237,
|
||||
43,12,0,87,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,30,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,111,
|
||||
43,13,0,95,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,33,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,7,255,6,0,6,6,255,5,246,0,6,27,255,5,229,0,6,86,255,5,186,0,4,8,64,222,255,5,123,0,3,255,8,249,26,0,3,255,8,121,0,4,255,6,254,137,1,0,4,255,3,245,219,157,52,0,19,
|
||||
43,25,0,178,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,19,255,6,0,6,38,228,255,6,118,0,4,255,6,0,5,40,230,255,5,252,100,0,5,255,6,0,4,43,232,255,5,249,83,0,6,255,6,0,3,45,234,255,5,243,68,0,7,255,6,0,2,47,235,255,5,236,54,0,8,255,6,0,1,50,237,255,5,228,42,0,9,255,6,53,239,255,5,218,31,0,10,255,6,240,255,5,207,22,0,11,255,11,194,15,0,12,255,11,116,0,13,255,12,110,0,12,255,6,241,255,6,112,0,11,255,6,60,244,255,6,114,0,10,255,6,0,1,66,247,255,6,115,0,9,255,6,0,2,74,249,255,6,117,0,8,255,6,0,3,82,251,255,6,119,0,7,255,6,0,4,89,253,255,6,121,0,6,255,6,0,5,98,254,255,6,123,0,5,255,6,0,6,106,255,7,125,0,4,255,6,0,7,115,255,7,127,0,225,
|
||||
43,12,0,87,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,6,255,6,0,111,
|
||||
43,38,0,255,0,255,0,25,255,6,0,2,30,128,206,237,244,214,156,52,0,5,48,149,212,243,242,216,151,45,0,9,255,6,0,1,109,244,255,7,142,4,0,1,8,147,255,7,253,124,0,8,255,6,130,255,10,149,5,189,255,10,108,0,7,255,17,254,193,255,11,245,19,0,6,255,31,112,0,6,255,7,228,90,18,15,77,233,255,7,229,91,18,16,83,236,255,5,179,0,6,255,6,242,35,0,4,99,255,6,245,37,0,4,93,255,5,224,0,6,255,6,134,0,5,40,255,6,139,0,5,20,255,5,243,0,6,255,6,55,0,5,13,255,6,60,0,6,252,255,5,0,6,255,6,15,0,5,4,255,6,18,0,6,252,255,5,0,6,255,6,2,0,6,255,6,2,0,6,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,6,255,6,0,7,255,6,0,7,255,6,0,255,0,90,
|
||||
43,26,0,255,0,112,255,6,0,2,7,96,177,223,247,240,212,147,40,0,9,255,6,0,1,74,222,255,7,252,119,0,8,255,6,112,253,255,10,104,0,7,255,18,244,18,0,6,255,19,111,0,6,255,7,249,133,40,7,26,121,251,255,5,178,0,6,255,6,254,74,0,5,121,255,5,224,0,6,255,6,160,0,6,42,255,5,242,0,6,255,6,67,0,6,14,255,6,0,6,255,6,19,0,6,4,255,6,0,6,255,6,2,0,6,1,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,237,
|
||||
43,25,0,255,0,102,6,86,149,204,228,246,247,229,206,151,89,8,0,11,2,116,232,255,10,233,119,3,0,8,20,192,255,14,194,22,0,6,9,200,255,16,201,9,0,5,144,255,18,145,0,4,31,249,255,5,244,127,44,10,8,42,126,243,255,5,249,31,0,3,118,255,5,243,48,0,6,48,244,255,5,117,0,3,188,255,5,126,0,8,126,255,5,187,0,3,225,255,5,42,0,8,43,255,5,223,0,3,246,255,5,8,0,8,9,255,5,245,0,3,246,255,5,8,0,8,9,255,5,245,0,3,225,255,5,42,0,8,43,255,5,223,0,3,188,255,5,125,0,8,125,255,5,187,0,3,118,255,5,243,46,0,6,45,243,255,5,117,0,3,31,249,255,5,243,125,43,8,8,41,123,242,255,5,249,31,0,4,145,255,18,145,0,5,10,201,255,16,201,10,0,6,20,192,255,14,195,22,0,8,2,117,232,255,10,234,120,3,0,11,7,86,150,205,230,247,248,231,207,153,90,8,0,231,
|
||||
43,26,0,255,0,112,255,6,0,2,21,116,194,229,249,232,194,113,14,0,9,255,6,0,1,98,238,255,7,229,73,0,8,255,6,124,255,10,251,84,0,7,255,18,245,38,0,6,255,19,189,0,6,255,7,229,99,26,5,25,96,227,255,6,48,0,5,255,6,234,29,0,5,27,233,255,5,134,0,5,255,6,113,0,7,113,255,5,193,0,5,255,6,38,0,7,38,255,5,228,0,5,255,6,7,0,7,8,255,5,246,0,5,255,6,7,0,7,8,255,5,246,0,5,255,6,38,0,7,38,255,5,228,0,5,255,6,112,0,7,113,255,5,193,0,5,255,6,233,27,0,5,27,233,255,5,134,0,5,255,7,227,98,25,4,24,95,226,255,6,48,0,5,255,19,189,0,6,255,18,245,38,0,6,255,6,125,255,10,251,84,0,7,255,6,0,1,100,240,255,7,230,74,0,8,255,6,0,2,23,120,195,231,250,233,195,114,14,0,9,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,43,
|
||||
43,26,0,255,0,115,14,113,193,232,249,230,196,119,23,0,2,255,6,0,8,75,230,255,7,240,101,0,1,255,6,0,7,87,251,255,10,125,255,6,0,6,41,247,255,18,0,6,193,255,19,0,5,51,255,6,227,97,25,5,26,98,228,255,7,0,5,136,255,5,233,27,0,5,27,233,255,6,0,5,195,255,5,112,0,7,113,255,6,0,5,230,255,5,37,0,7,38,255,6,0,5,247,255,5,7,0,7,8,255,6,0,5,247,255,5,7,0,7,8,255,6,0,5,230,255,5,37,0,7,38,255,6,0,5,194,255,5,112,0,7,113,255,6,0,5,134,255,5,233,27,0,5,27,233,255,6,0,5,50,255,6,227,96,24,4,24,97,227,255,7,0,6,192,255,19,0,6,41,247,255,18,0,7,87,251,255,10,125,255,6,0,8,76,231,255,7,240,101,0,1,255,6,0,9,14,114,195,233,250,231,196,120,23,0,2,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,20,255,6,0,29,
|
||||
43,18,0,255,255,6,0,3,57,156,211,239,255,1,252,0,3,255,6,0,1,15,177,255,5,252,0,3,255,6,12,204,255,6,253,0,3,255,6,166,255,7,254,0,3,255,14,254,0,3,255,8,188,77,21,5,27,89,191,0,3,255,7,139,0,10,255,6,204,2,0,10,255,6,97,0,11,255,6,36,0,11,255,6,9,0,11,255,6,0,12,255,6,0,12,255,6,0,12,255,6,0,12,255,6,0,12,255,6,0,12,255,6,0,12,255,6,0,12,255,6,0,171,
|
||||
43,21,0,255,0,44,44,125,181,218,239,250,250,241,221,196,162,123,76,25,0,5,20,176,255,14,0,4,11,216,255,15,0,4,129,255,16,0,4,212,255,5,212,80,25,5,18,46,98,163,240,255,2,0,4,245,255,5,35,0,7,6,87,200,0,4,244,255,4,254,14,0,14,206,255,5,178,53,6,0,12,118,255,7,251,223,187,148,99,39,0,7,8,198,255,12,215,108,4,0,5,11,136,241,255,12,189,7,0,6,10,81,144,193,231,255,9,117,0,11,10,45,100,211,255,5,206,0,14,31,255,5,244,0,3,199,85,5,0,8,38,255,5,242,0,3,255,2,240,167,104,57,25,9,6,26,85,215,255,5,202,0,3,255,17,108,0,3,255,16,186,3,0,3,255,14,246,138,5,0,4,25,76,122,160,194,218,238,248,253,245,233,204,164,98,21,0,193,
|
||||
43,17,0,157,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,8,255,15,0,2,255,15,0,2,255,15,0,2,255,15,0,2,255,15,0,5,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,11,255,6,0,11,247,255,5,23,0,10,232,255,5,153,26,2,0,8,192,255,11,0,5,129,255,11,0,5,31,246,255,10,0,6,89,249,255,9,0,7,38,144,207,240,253,255,5,0,154,
|
||||
43,26,0,255,0,112,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,6,0,8,255,6,0,6,255,5,254,0,8,255,6,0,6,255,5,253,0,8,255,6,0,6,255,5,252,0,8,255,6,0,6,255,5,250,0,8,255,6,0,6,255,5,248,0,8,255,6,0,6,255,5,248,0,8,255,6,0,6,255,5,248,0,7,2,255,6,0,6,255,5,253,0,7,19,255,6,0,6,255,6,9,0,6,66,255,6,0,6,244,255,5,40,0,6,158,255,6,0,6,225,255,5,122,0,5,71,253,255,6,0,6,179,255,5,250,118,25,6,38,130,248,255,7,0,6,112,255,19,0,6,19,244,255,18,0,7,105,255,10,254,113,255,6,0,8,119,252,255,7,225,77,0,1,255,6,0,9,39,146,212,241,248,226,180,101,9,0,2,255,6,0,237,
|
||||
43,23,0,255,0,68,207,255,5,156,0,8,157,255,5,207,0,1,110,255,5,242,10,0,6,11,243,255,5,109,0,1,19,249,255,5,94,0,6,95,255,5,249,19,0,2,172,255,5,191,0,6,192,255,5,170,0,3,75,255,5,254,33,0,4,34,254,255,5,73,0,3,3,230,255,5,129,0,4,130,255,5,228,3,0,4,136,255,5,224,2,0,2,2,225,255,5,134,0,5,40,255,6,68,0,2,69,255,6,37,0,6,198,255,5,165,0,2,166,255,5,195,0,7,101,255,5,246,15,16,247,255,5,98,0,7,14,245,255,5,103,104,255,5,244,12,0,8,162,255,5,200,201,255,5,159,0,9,65,255,12,62,0,9,1,223,255,10,219,0,11,127,255,10,123,0,11,31,254,255,8,253,28,0,12,188,255,8,184,0,13,91,255,8,87,0,13,9,241,255,6,238,7,0,14,153,255,6,148,0,214,
|
||||
43,33,0,255,0,208,222,255,5,85,0,5,71,255,5,71,0,5,86,255,5,222,0,2,155,255,5,151,0,5,134,255,5,133,0,5,153,255,5,155,0,2,88,255,5,218,0,5,196,255,5,195,0,5,220,255,5,88,0,2,22,254,255,5,29,0,3,9,249,255,5,249,8,0,3,31,255,5,254,22,0,3,210,255,5,96,0,3,65,255,7,64,0,3,98,255,5,210,0,4,143,255,5,163,0,3,127,255,7,127,0,3,165,255,5,143,0,4,76,255,5,229,0,3,189,255,3,192,255,3,189,0,3,231,255,5,76,0,4,13,251,255,5,40,0,1,5,245,255,3,67,255,3,246,5,0,1,43,255,5,251,13,0,5,198,255,5,107,0,1,58,255,3,227,0,1,227,255,3,58,0,1,110,255,5,198,0,6,131,255,5,174,0,1,120,255,3,165,0,1,165,255,3,121,0,1,177,255,5,131,0,6,64,255,5,238,2,182,255,3,102,0,1,102,255,3,183,3,240,255,5,64,0,6,7,246,255,5,54,241,255,3,40,0,1,40,255,3,242,59,255,5,246,7,0,7,186,255,5,169,255,3,233,0,3,232,255,3,175,255,5,186,0,8,119,255,5,254,255,3,172,0,3,171,255,9,119,0,8,52,255,9,110,0,3,108,255,9,52,0,8,2,238,255,8,47,0,3,46,255,8,238,2,0,9,174,255,7,239,2,0,3,1,237,255,7,174,0,10,107,255,7,179,0,5,177,255,7,107,0,10,40,255,7,117,0,5,114,255,7,40,0,11,229,255,6,55,0,5,51,255,6,229,0,255,0,48,
|
||||
43,23,0,255,0,68,160,255,6,210,9,0,4,10,213,255,6,160,0,1,11,214,255,6,154,0,4,160,255,6,213,10,0,2,44,246,255,6,89,0,2,96,255,6,245,42,0,4,99,255,6,242,37,42,245,255,6,96,0,6,163,255,6,207,213,255,6,160,0,7,12,216,255,12,213,10,0,8,46,247,255,10,245,42,0,10,102,255,10,96,0,12,166,255,8,160,0,13,13,228,255,6,227,10,0,13,61,252,255,6,253,64,0,12,15,224,255,8,227,17,0,11,167,255,10,170,0,10,94,255,12,97,0,8,34,242,255,6,254,255,5,243,35,0,6,3,198,255,6,150,144,255,6,200,4,0,5,129,255,6,214,9,7,210,255,6,131,0,4,59,252,255,5,248,47,0,2,44,247,255,5,252,60,0,2,14,223,255,6,113,0,4,110,255,6,223,15,0,1,165,255,6,185,1,0,4,1,182,255,6,165,0,207,
|
||||
43,23,0,255,0,67,203,255,5,176,0,8,147,255,5,209,0,1,98,255,5,252,29,0,6,5,236,255,5,115,0,1,9,238,255,5,132,0,6,80,255,5,252,24,0,2,142,255,5,232,5,0,5,174,255,5,183,0,3,37,254,255,5,88,0,4,18,249,255,5,89,0,4,186,255,5,194,0,4,107,255,5,241,9,0,4,81,255,6,44,0,3,201,255,5,157,0,5,3,227,255,5,150,0,2,39,255,6,63,0,6,125,255,5,242,13,0,1,133,255,5,223,1,0,6,24,250,255,5,105,1,225,255,5,131,0,8,169,255,5,210,66,255,6,37,0,8,64,255,6,210,255,5,199,0,10,213,255,11,105,0,10,108,255,10,249,17,0,10,14,243,255,9,173,0,12,152,255,9,79,0,12,47,255,8,235,5,0,13,197,255,7,147,0,14,91,255,7,53,0,14,6,234,255,5,214,0,15,3,231,255,5,121,0,15,77,255,5,253,29,0,14,2,193,255,5,183,0,13,14,51,169,255,6,72,0,12,228,255,8,194,0,13,228,255,7,244,39,0,13,228,255,6,238,65,0,14,228,255,3,243,207,133,23,0,35,
|
||||
43,21,0,255,0,41,255,18,0,3,255,18,0,3,255,18,0,3,255,18,0,3,255,17,209,0,11,12,203,255,6,232,30,0,10,5,184,255,6,247,55,0,10,1,163,255,7,88,0,11,140,255,7,128,0,11,115,255,7,167,0,11,91,254,255,6,200,8,0,10,70,250,255,6,225,23,0,10,51,243,255,6,243,46,0,10,36,233,255,6,253,77,0,10,23,221,255,7,115,0,11,206,255,17,0,3,255,18,0,3,255,18,0,3,255,18,0,3,255,18,0,190,
|
||||
43,26,0,194,13,104,179,225,244,255,4,0,16,54,227,255,8,0,15,20,234,255,9,0,15,127,255,10,0,15,199,255,5,228,85,23,4,0,16,238,255,5,89,0,19,253,255,5,27,0,19,255,6,5,0,19,255,6,0,20,255,6,0,19,3,255,6,0,19,18,255,5,251,0,19,61,255,5,237,0,19,155,255,5,200,0,16,7,42,143,255,6,128,0,15,255,9,217,17,0,15,255,7,234,136,17,0,16,255,7,254,193,52,0,16,255,9,245,41,0,16,8,40,133,252,255,5,156,0,19,138,255,5,217,0,19,47,255,5,245,0,19,11,255,5,254,0,20,255,6,0,20,255,6,0,20,255,6,3,0,19,254,255,5,21,0,19,240,255,5,77,0,19,206,255,5,221,77,21,3,0,16,136,255,10,0,15,25,240,255,9,0,16,62,232,255,8,0,17,16,110,182,226,245,255,4,0,83,
|
||||
43,13,0,83,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,9,255,4,0,17,
|
||||
43,26,0,187,255,4,244,224,179,104,13,0,17,255,8,226,54,0,16,255,9,234,19,0,15,255,10,126,0,16,4,23,85,229,255,5,199,0,19,90,255,5,237,0,19,28,255,5,253,0,19,7,255,6,0,20,255,6,0,20,255,6,0,20,255,6,3,0,19,252,255,5,17,0,19,238,255,5,59,0,19,201,255,5,151,0,19,129,255,5,254,141,42,7,0,16,17,218,255,9,0,16,17,135,234,255,7,0,16,51,192,254,255,7,0,15,41,244,255,9,0,15,157,255,5,252,132,39,8,0,16,218,255,5,135,0,19,246,255,5,46,0,19,255,6,9,0,19,255,6,0,20,255,6,0,19,3,255,6,0,19,22,255,5,254,0,19,78,255,5,239,0,16,3,21,77,221,255,5,206,0,15,255,10,135,0,15,255,9,240,25,0,15,255,8,232,62,0,16,255,4,245,226,182,110,16,0,90,
|
||||
43,30,0,255,0,255,0,56,33,0,9,20,113,181,228,248,238,212,162,95,25,0,8,10,121,246,0,7,21,150,248,255,8,253,198,124,65,21,4,21,63,136,235,255,2,0,7,241,255,22,0,7,255,22,241,0,7,255,2,249,157,72,25,5,23,65,126,199,253,255,8,249,152,22,0,7,255,1,179,34,0,8,25,96,163,212,239,249,229,184,117,22,0,9,113,0,255,0,255,0,25,
|
||||
43,22,0,200,255,18,0,4,255,18,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,2,0,14,255,2,0,4,255,18,0,4,255,18,0,46,
|
||||
43,18,0,131,9,116,204,243,243,198,106,6,0,9,31,212,255,6,207,28,0,7,10,213,255,8,208,7,0,6,117,255,2,249,117,24,24,119,250,255,2,108,0,6,205,255,2,117,0,4,120,255,2,199,0,6,245,255,2,24,0,4,25,255,2,243,0,6,245,255,2,22,0,4,23,255,2,243,0,6,208,255,2,111,0,4,114,255,2,201,0,6,123,255,2,247,112,23,23,114,248,255,2,112,0,6,12,219,255,8,213,9,0,7,37,219,255,6,212,32,0,9,12,123,208,245,244,201,111,7,0,255,0,182,
|
||||
43,24,0,134,95,255,4,136,0,17,34,242,255,3,153,0,17,4,199,255,3,168,2,0,17,130,255,3,182,5,0,17,60,252,255,2,194,9,0,17,15,223,255,2,206,15,0,18,165,255,2,217,21,0,64,9,92,155,209,231,248,242,221,179,112,24,0,11,3,122,236,255,9,246,140,8,0,8,22,195,255,13,202,25,0,6,10,201,255,15,202,8,0,5,145,255,5,246,129,41,7,14,74,206,255,5,140,0,4,31,249,255,4,252,67,0,5,9,203,255,4,246,24,0,3,118,255,5,146,0,7,69,255,5,112,0,3,188,255,5,60,0,7,11,255,5,179,0,3,225,255,19,221,0,3,246,255,19,242,0,3,246,255,20,0,3,225,255,20,0,3,190,255,5,25,0,17,120,255,5,109,0,17,34,251,255,4,238,45,0,9,15,103,205,0,5,150,255,5,245,137,55,15,3,15,33,75,123,191,251,255,2,0,5,13,206,255,17,0,6,24,198,255,16,0,7,3,120,233,255,14,0,9,6,85,148,202,228,245,253,246,236,216,192,159,122,76,25,0,218,
|
||||
43,24,0,133,95,255,4,136,0,17,34,242,255,3,153,0,17,4,199,255,3,168,2,0,17,130,255,3,182,5,0,17,60,252,255,2,194,9,0,17,15,223,255,2,206,15,0,18,165,255,2,217,21,0,62,23,71,119,167,202,228,243,252,247,234,216,173,122,36,0,10,255,14,180,31,0,8,255,15,235,39,0,7,255,16,211,2,0,6,255,2,201,117,64,26,10,4,19,57,138,249,255,5,84,0,6,185,47,0,9,90,255,5,161,0,17,8,255,5,216,0,7,10,80,150,192,226,240,251,255,9,238,0,6,107,234,255,15,253,0,5,147,255,18,0,4,71,255,19,0,4,173,255,5,241,119,44,11,0,3,1,255,6,0,4,228,255,5,72,0,6,25,255,6,0,4,249,255,5,9,0,6,108,255,6,0,4,236,255,5,67,0,5,46,239,255,6,0,4,185,255,5,231,93,25,5,35,122,244,255,7,0,4,85,255,19,0,5,174,255,11,124,255,6,0,5,8,160,255,8,238,99,0,1,255,6,0,7,57,158,219,245,247,226,189,115,21,0,2,255,6,0,218,
|
||||
};
|
||||
|
||||
unsigned char *ftv = fonttable;
|
||||
|
||||
/* fonttable is obtained with:
|
||||
|
||||
if(ch >= 32) {
|
||||
printf("%d,%d,", txt->h, txt->w);
|
||||
int rle_last = -1, rle_q = 0;
|
||||
for(int j=0; j <txt->h;j++) {
|
||||
for(int i=0; i < txt->w; i++) {
|
||||
int c = (unsigned char) (qpixel(txt, i, j) >> 24);
|
||||
if(c == rle_last && rle_q < 255) rle_q++;
|
||||
else {
|
||||
if(rle_last != -1) printf("%d,%d,", rle_last, rle_q);
|
||||
if(c == 0 || c == 255) rle_last = c, rle_q = 1;
|
||||
else { rle_last = -1; printf("%d,", c); }
|
||||
}
|
||||
}
|
||||
}
|
||||
if(rle_last != -1) printf("%d,%d,", rle_last, rle_q);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
void loadCompressedChar(int &otwidth, int &otheight, int *tpix) {
|
||||
otheight = *(ftv++);
|
||||
otwidth = *(ftv++);
|
||||
int left = otwidth * otheight;
|
||||
while(left) {
|
||||
int x = *(ftv++);
|
||||
if(x == 0 || x == 255) {
|
||||
x = x * 0x1010101;
|
||||
int q = *(ftv++);
|
||||
left -= q;
|
||||
while(q--) *(tpix++) = x;
|
||||
}
|
||||
else {
|
||||
*(tpix++) = (x << 24) | 0xFFFFFF;
|
||||
left--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
#define VER "9.4c"
|
||||
#define VERNUM 9403
|
||||
#define VERNUM_HEX 0x9403
|
||||
|
||||
#define GEN_M 0
|
||||
#define GEN_F 1
|
||||
#define GEN_N 2
|
||||
#define GEN_O 3
|
||||
|
||||
#ifdef MOBILE
|
||||
#define MOBWEB
|
||||
#endif
|
||||
|
||||
#ifdef WEB
|
||||
#define MOBWEB
|
||||
#define ONEGRAPH
|
||||
#endif
|
||||
|
||||
#ifdef IOS
|
||||
#define ONEGRAPH
|
||||
#endif
|
||||
|
||||
#ifdef MOBWEB
|
||||
#define NORUG
|
||||
#define NOEDIT
|
||||
#define NOMODEL
|
||||
#endif
|
||||
|
||||
#ifdef MINI
|
||||
#define NORUG
|
||||
#define NOEDIT
|
||||
#define NOMODEL
|
||||
#define NOSAVE
|
||||
#define NOCONFIG
|
||||
#define NOTRANS
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MOBILE
|
||||
#define EXTRALICENSE "\n\nHyperRogue soundtrack by Shawn Parrotte (http://www.shawnparrotte.com), under the Creative Commons BY-SA 3.0 license, http://creativecommons.org/licenses/by-sa/3.0/"
|
||||
#undef XEXTRALICENSE
|
||||
|
||||
#ifndef FAKEMOBILE
|
||||
#define SDLK_F1 (123001)
|
||||
#define SDLK_F2 (123002)
|
||||
#define SDLK_F3 (123003)
|
||||
#define SDLK_F4 (123004)
|
||||
#define SDLK_F5 (123005)
|
||||
#define SDLK_F6 (123006)
|
||||
#define SDLK_F7 (123007)
|
||||
#define SDLK_F10 (123010)
|
||||
#define SDLK_ESCAPE (123099)
|
||||
#define SDLK_F12 (123012)
|
||||
#define SDLK_HOME (123013)
|
||||
#define SDLK_LEFT (123014)
|
||||
#define SDLK_RIGHT (123015)
|
||||
#define MIX_MAX_VOLUME 128
|
||||
#define SDLK_UP (123021)
|
||||
#define SDLK_DOWN (123022)
|
||||
#define SDLK_PAGEUP (123023)
|
||||
#define SDLK_PAGEDOWN (123024)
|
||||
#define SDLK_RETURN (123025)
|
||||
#define SDLK_KP1 (123031)
|
||||
#define SDLK_KP2 (123032)
|
||||
#define SDLK_KP3 (123033)
|
||||
#define SDLK_KP4 (123034)
|
||||
#define SDLK_KP5 (123035)
|
||||
#define SDLK_KP6 (123036)
|
||||
#define SDLK_KP7 (123037)
|
||||
#define SDLK_KP8 (123038)
|
||||
#define SDLK_KP9 (123039)
|
||||
#define SDLK_KP_PERIOD (123051)
|
||||
#define SDLK_DELETE (123052)
|
||||
#define SDLK_DELETE (123052)
|
||||
#endif
|
||||
|
||||
int fontscale = 100;
|
||||
bool buttonclicked;
|
||||
void gdpush(int t);
|
||||
#endif
|
||||
|
||||
// desktop
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef USE_SDL
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#ifndef MAC
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#ifdef USE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
#else
|
||||
#define unordered_map map
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
string s0;
|
||||
void addMessage(string s, char spamtype = 0);
|
||||
|
||||
#ifdef ANDROID
|
||||
FILE *debfile;
|
||||
#endif
|
||||
|
||||
FILE *debugfile;
|
||||
int debugflags;
|
||||
|
||||
#ifdef USE_COMMANDLINE
|
||||
const char *scorefile = "hyperrogue.log";
|
||||
const char *conffile = "hyperrogue.ini";
|
||||
string levelfile = "hyperrogue.lev";
|
||||
string picfile = "hyperrogue.pic";
|
||||
const char *musicfile = "";
|
||||
const char *loadlevel = NULL;
|
||||
#endif
|
||||
|
||||
#define S7 (sphere?5:7)
|
||||
#define S42 (S7*6)
|
||||
#define S14 (S7*2)
|
||||
#define S21 (S7*3)
|
||||
#define S28 (S7*4)
|
||||
#define S84 (S7*12)
|
||||
|
||||
#include "util.cpp"
|
||||
#include "hyperpoint.cpp"
|
||||
#include "patterns.cpp"
|
||||
#include "classes.cpp"
|
||||
#include "fieldpattern.cpp"
|
||||
#include "heptagon.cpp"
|
||||
#include "language.cpp"
|
||||
#include "hyper.h"
|
||||
#include "cell.cpp"
|
||||
#include "flags.cpp"
|
||||
#include "yendor.cpp"
|
||||
#include "complex.cpp"
|
||||
#include "game.cpp"
|
||||
#include "landgen.cpp"
|
||||
#include "orbs.cpp"
|
||||
#include "system.cpp"
|
||||
#include "geometry.cpp"
|
||||
#include "polygons.cpp"
|
||||
#include "mapeditor.cpp"
|
||||
#ifndef MOBILE
|
||||
#include "netgen.cpp"
|
||||
#endif
|
||||
#include "graph.cpp"
|
||||
#include "sound.cpp"
|
||||
#include "achievement.cpp"
|
||||
#ifndef MOBILE
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
bool fixseed = false;
|
||||
|
||||
void initAll() {
|
||||
ca::init();
|
||||
arg::read(1);
|
||||
srand(time(NULL));
|
||||
shrand(fixseed ? 0 : time(NULL));
|
||||
|
||||
achievement_init(); // not in ANDROID
|
||||
|
||||
eLand f = firstland;
|
||||
|
||||
// initlanguage();
|
||||
initgraph();
|
||||
#ifndef NOSAVE
|
||||
loadsave();
|
||||
#endif
|
||||
resetGeometry();
|
||||
initcells();
|
||||
|
||||
shmup::safety = safety;
|
||||
initgame();
|
||||
restartGraph();
|
||||
|
||||
if(!shmup::on) {
|
||||
restoreGolems(items[itOrbLife], moGolem); items[itOrbLife] = 0;
|
||||
restoreGolems(items[itOrbFriend], moTameBomberbird); items[itOrbFriend] = 0;
|
||||
restoreGolems(kills[moPrincessMoved], moPrincess, princess::saveHP); kills[moPrincessMoved] = 0;
|
||||
restoreGolems(kills[moPrincessArmedMoved], moPrincessArmed, princess::saveArmedHP); kills[moPrincessArmedMoved] = 0;
|
||||
}
|
||||
|
||||
firstland = f;
|
||||
}
|
||||
|
||||
void finishAll() {
|
||||
achievement_final(!items[itOrbSafety]);
|
||||
|
||||
#ifndef NOSAVE
|
||||
saveStats();
|
||||
#endif
|
||||
offscreen.clear();
|
||||
clearMemory();
|
||||
#ifndef MOBILE
|
||||
cleargraph();
|
||||
#endif
|
||||
|
||||
achievement_close();
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
string buildScoreDescription() {
|
||||
string s;
|
||||
time_t timer;
|
||||
timer = time(NULL);
|
||||
char buf[128]; strftime(buf, 128, "%c", localtime(&timer));
|
||||
char buf2[128];
|
||||
|
||||
s += XLAT("HyperRogue for Android");
|
||||
s += " ("VER"), http://www.roguetemple.com/z/hyper.php\n";
|
||||
s += XLAT("Date: %1 time: %2 s ", buf, its(savetime + time(NULL) - timerstart));
|
||||
s += XLAT("distance: %1\n", its(celldist(cwt.c)));
|
||||
// s += buf2;
|
||||
if(cheater) s += XLAT("Cheats: ") + its(cheater) + "\n";
|
||||
s += XLAT("Score: ") + its(gold());
|
||||
|
||||
for(int i=0; i<ittypes; i++) if(items[i]) {
|
||||
string t = XLATN(iinf[i].name);
|
||||
sprintf(buf2, " %s (%d)", t.c_str(), items[i]);
|
||||
s += buf2;
|
||||
}
|
||||
s += "\n";
|
||||
s += XLAT("Kills: ") + its(tkills());
|
||||
for(int i=1; i<motypes; i++) if(kills[i]) {
|
||||
string t = XLATN(minf[i].name);
|
||||
sprintf(buf2, " %s (%d)", t.c_str(), kills[i]);
|
||||
s += buf2;
|
||||
}
|
||||
s += "\n";
|
||||
|
||||
for(int i=0; i<gamelog.size(); i++) if(gamelog[i].msg != "") s += gamelog[i].msg + "\n";
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOBILE
|
||||
|
||||
bool lclicked = false, clicked = false;
|
||||
string lmouseovers;
|
||||
bool inmenu = false;
|
||||
|
||||
bool longclick;
|
||||
|
||||
void handleScoreClick();
|
||||
void openURL();
|
||||
void displayTexts();
|
||||
void controlMusic(int ticks);
|
||||
|
||||
void showHelp(MOBPAR_FORMAL, string nhelp) {
|
||||
help = nhelp;
|
||||
// helptext = help;
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
}
|
||||
|
||||
bool useRangedOrb;
|
||||
|
||||
void handleclick(MOBPAR_FORMAL) {
|
||||
|
||||
if(!shmup::on && andmode == 0 && cmode == emNormal && canmove && !useRangedOrb && vid.mobilecompasssize > 0) {
|
||||
using namespace shmupballs;
|
||||
int dx = mousex - xmove;
|
||||
int dy = mousey - yb;
|
||||
int h = hypot(dx, dy);
|
||||
if(h < rad) {
|
||||
if(h < rad*SKIPFAC) movepcto(MD_WAIT);
|
||||
else {
|
||||
double d = revcontrol ? -1 : 1;
|
||||
mouseh = hpxy(dx * d / rad, dy * d / rad);
|
||||
mousemovement();
|
||||
}
|
||||
getcstat = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(buttonclicked || outofmap(mouseh)) {
|
||||
|
||||
if(andmode == 0 && getcstat == 'g' && !shmup::on) {
|
||||
movepcto(MD_DROP);
|
||||
getcstat = 0;
|
||||
}
|
||||
|
||||
else if(getcstat != SDLK_F1) {
|
||||
int px = mousex < vid.xcenter ? 0 : 1;
|
||||
int py = mousey < vid.ycenter ? 0 : 1;
|
||||
|
||||
if(cmode == (canmove ? emNormal : emQuit)) {
|
||||
if(px == 0 && py == 1) {
|
||||
if(andmode == 0 && shmup::on) ;
|
||||
else andmode = 10;
|
||||
}
|
||||
if(px == 1 && py == 1) {
|
||||
if(andmode == 0 && shmup::on) ; // just fire, do not change modes
|
||||
else {
|
||||
if(andmode == 1) {
|
||||
centerpc(INF);
|
||||
View = Id;
|
||||
viewctr.h = cwt.c->master;
|
||||
}
|
||||
andmode = 11;
|
||||
}
|
||||
}
|
||||
if(px == 0 && py == 0) andmode = 22;
|
||||
if(px == 1 && py == 0) andmode = 13;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if(andmode == 0 && help != "@") {
|
||||
addMessage(mouseovers);
|
||||
showHelp(MOBPAR_ACTUAL, help);
|
||||
andmode = 10;
|
||||
getcstat = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(andmode == 0 && cmode == (canmove ? emNormal : emQuit) && !outofmap(mouseh)) {
|
||||
|
||||
bool forcetarget = longclick;
|
||||
|
||||
if(mouseover && targetclick && targetRangedOrb(mouseover, forcetarget ? roMouseForce : roMouse)) {
|
||||
;
|
||||
}
|
||||
else if(!forcetarget) movepcto(mousedest);
|
||||
}
|
||||
|
||||
if(andmode == 10) {
|
||||
if(!playerfound) {
|
||||
centerpc(INF);
|
||||
View = Id;
|
||||
viewctr.h = cwt.c->master;
|
||||
}
|
||||
playermoved = true;
|
||||
}
|
||||
|
||||
if(andmode >= 10) andmode -= 10;
|
||||
|
||||
if(andmode == 3) cmode = emMenu, andmode = 0;
|
||||
}
|
||||
|
||||
int touchedAt;
|
||||
|
||||
int getticks();
|
||||
|
||||
void mobile_draw(MOBPAR_FORMAL) {
|
||||
|
||||
optimizeview();
|
||||
|
||||
int lastt = ticks; ticks = getticks();
|
||||
if(lastt > ticks) lastt = ticks;
|
||||
int tdiff = ticks - lastt;
|
||||
|
||||
if(playermoved && vid.sspeed > -4.99)
|
||||
centerpc(tdiff / 1000.0 * exp(vid.sspeed));
|
||||
|
||||
if(shmup::on && (andmode == 0 || andmode == 10) && cmode == emNormal)
|
||||
shmup::turn(tdiff);
|
||||
|
||||
safety = false;
|
||||
vid.fsize = (min(vid.xres, vid.yres) * fontscale + 50) / 3200;
|
||||
|
||||
hyperpoint mouseoh = mouseh;
|
||||
gtouched = mousepressed = clicked;
|
||||
|
||||
longclick = lclicked && ticks > touchedAt + 500;
|
||||
useRangedOrb =
|
||||
longclick || (!(vid.shifttarget & 2) && haveRangedOrb() && lmouseover && lmouseover->cpdist > 1);
|
||||
|
||||
targetclick = ((vid.shifttarget & 2) && !shmup::on) ? longclick : true;
|
||||
|
||||
if(shmup::on) {
|
||||
using namespace shmupballs;
|
||||
if(hypot(mousex - xfire, mousey - yb) < rad) targetclick = false;
|
||||
if(hypot(mousex - xmove, mousey - yb) < rad) targetclick = false;
|
||||
}
|
||||
|
||||
if(cmode == emNormal) {
|
||||
lmouseover = (gtouched && lclicked) ? mouseover : NULL;
|
||||
if(!shmup::on && !useRangedOrb && vid.mobilecompasssize) {
|
||||
using namespace shmupballs;
|
||||
int dx = mousex - xmove;
|
||||
int dy = mousey - yb;
|
||||
int h = hypot(dx, dy);
|
||||
if(h < rad) {
|
||||
if(h < rad*SKIPFAC) { lmouseover = cwt.c; mousedest.d = -1; }
|
||||
else {
|
||||
double d = revcontrol ? -1 : 1;
|
||||
mouseh = hpxy(dx * d / rad, dy * d / rad);
|
||||
calcMousedest();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(andmode == 0 && !useRangedOrb && gtouched && lclicked) {
|
||||
lmouseover = mousedest.d >= 0 ? cwt.c->mov[(cwt.spin + mousedest.d) % cwt.c->type] : cwt.c;
|
||||
}
|
||||
}
|
||||
mouseh = gethyper(mousex, mousey);
|
||||
|
||||
// if(debfile) fprintf(debfile, "d1\n"), fflush(debfile);
|
||||
frames++;
|
||||
if(conformal::on) conformal::apply();
|
||||
|
||||
if(ticks > lastt) tortoise::updateVals(ticks - lastt);
|
||||
|
||||
if(clicked && !lclicked) touchedAt = ticks;
|
||||
|
||||
graphdata.clear();
|
||||
getcstat = 0; shiftmul = 1; getcshift = 1;
|
||||
drawscreen();
|
||||
shiftmul = getcshift;
|
||||
calcMousedest();
|
||||
|
||||
if(lclicked && !clicked && !inmenu) handleclick(MOBPAR_ACTUAL);
|
||||
|
||||
if(inmenu && !clicked && !lclicked) inmenu = false;
|
||||
|
||||
bool keyreact = lclicked && !clicked;
|
||||
|
||||
if(cmode == emOverview || cmode == emTactic) {
|
||||
using namespace dialog::zoom;
|
||||
if(zoomoff || (cmode != emOverview && cmode != emTactic)) {
|
||||
zoomf = 1; shiftx = shifty = 0; zoomoff = false; return;
|
||||
}
|
||||
if(clicked && !lclicked) {
|
||||
zoomf = 3;
|
||||
}
|
||||
if(zoomf == 3) {
|
||||
shiftx = -2*mousex;
|
||||
shifty = -2*mousey;
|
||||
}
|
||||
if(!clicked && zoomf > 1) { zoomoff = true; }
|
||||
}
|
||||
|
||||
if(inslider) keyreact = true;
|
||||
|
||||
#ifdef ANDROID
|
||||
if(getcstat == 's'-96) {
|
||||
cmode = canmove ? emQuit : emNormal;
|
||||
shareScore(MOBPAR_ACTUAL);
|
||||
cmode = emNormal;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(andmode == 2 && cmode != emNormal) andmode = 12;
|
||||
|
||||
if((cmode == emQuit && !canmove && keyreact && lclicked && !clicked) && !buttonclicked) {
|
||||
cmode = emNormal; printf("back to quit\n");
|
||||
}
|
||||
else if(cmode == emScores) handleScoreKeys(0);
|
||||
else if(getcstat && keyreact) {
|
||||
|
||||
if(cmode == (canmove ? emQuit : emNormal))
|
||||
handleQuit(getcstat, getcstat);
|
||||
|
||||
else {
|
||||
if(cmode != emNormal && cmode != emQuit) inmenu = true;
|
||||
if(cmode == emMenu && getcstat == 'q') openURL();
|
||||
else { extra ex; handlekey(getcstat, getcstat, ex); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef IOS
|
||||
displayTexts();
|
||||
#endif
|
||||
|
||||
if((cmode != emVisual1 && cmode != emScores)) {
|
||||
|
||||
if(clicked && lclicked && andmode == 1 && !inmenu) {
|
||||
if(!outofmap(mouseoh) && !outofmap(mouseh) && mouseoh[2] < 50 && mouseh[2] < 50) {
|
||||
panning(mouseoh, mouseh);
|
||||
}
|
||||
}
|
||||
|
||||
if(andmode == 1 && lclicked && !clicked && !inmenu && mouseover)
|
||||
performMarkCommand(mouseover);
|
||||
|
||||
if(clicked && andmode == 2 && (mouseover != lmouseover || mouseovers != lmouseovers) && cmode == emNormal) {
|
||||
addMessage(mouseovers);
|
||||
lmouseovers = mouseovers;
|
||||
}
|
||||
|
||||
if(andmode == 10 && clicked != lclicked) andmode = 0;
|
||||
if(andmode == 20 && clicked != lclicked) andmode = 10;
|
||||
|
||||
if(andmode == 2 && lclicked && !clicked) {
|
||||
if(cmode == emNormal)
|
||||
showHelp(MOBPAR_ACTUAL, help);
|
||||
else if(cmode != emScores && cmode != emPickScores)
|
||||
cmode = emNormal;
|
||||
}
|
||||
|
||||
else if(andmode == 4) {
|
||||
achievement_final(false);
|
||||
}
|
||||
|
||||
if(clicked && andmode == 2 && (mouseover != lmouseover || mouseovers != lmouseovers)) {
|
||||
addMessage(mouseovers);
|
||||
showHelp(MOBPAR_ACTUAL, help);
|
||||
lmouseovers = mouseovers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(clicked != lclicked)
|
||||
flashMessages();
|
||||
|
||||
// END
|
||||
lclicked = clicked;
|
||||
|
||||
#ifdef IOS
|
||||
controlMusic(ticks - lastt);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOBILE
|
||||
#include "google-games.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
1963
landgen.cpp
1963
landgen.cpp
File diff suppressed because it is too large
Load Diff
11
langen.cpp
11
langen.cpp
|
@ -136,10 +136,13 @@ void setstats(set<string>& s, const char* bn) {
|
|||
int main() {
|
||||
|
||||
nothe.insert("R'Lyeh");
|
||||
nothe.insert("Camelot");
|
||||
plural.insert("Crossroads");
|
||||
plural.insert("Crossroads II");
|
||||
plural.insert("Crossroads III");
|
||||
plural.insert("Elemental Planes");
|
||||
plural.insert("Crossroads IV");
|
||||
plural.insert("Kraken Depths");
|
||||
|
||||
#define S(a,b) d[1].add(a,b);
|
||||
#define N(a,b,c,d,e,f) \
|
||||
|
@ -188,8 +191,8 @@ int main() {
|
|||
string mis = "";
|
||||
for(int i=1; i<NUMLAN; i++) if(d[i].count(*x) == 0)
|
||||
mis += d[i]["EN"];
|
||||
if(mis != "" && mis != "TR" && mis != "TRDE" && mis != "DE")
|
||||
printf("#warning Missing [%s]: %s\n", mis.c_str(), escape(*x, "?"));
|
||||
if(mis != "")
|
||||
printf("// #warning Missing [%s]: %s\n", mis.c_str(), escape(*x, "?"));
|
||||
}
|
||||
|
||||
s.clear();
|
||||
|
@ -202,8 +205,8 @@ int main() {
|
|||
string mis = "";
|
||||
for(int i=1; i<NUMLAN; i++) if(nouns[i].count(*x) == 0)
|
||||
mis += d[i]["EN"];
|
||||
if(mis != "" && mis != "TR" && mis != "TRDE" && mis != "DE")
|
||||
printf("#warning Missing [%s]: %s\n", mis.c_str(), escape(*x, "?"));
|
||||
if(mis != "")
|
||||
printf("// #warning Missing [%s]: %s\n", mis.c_str(), escape(*x, "?"));
|
||||
}
|
||||
|
||||
#ifdef CHECKALL
|
||||
|
|
1123
language-cz.cpp
1123
language-cz.cpp
File diff suppressed because it is too large
Load Diff
4392
language-data.cpp
4392
language-data.cpp
File diff suppressed because it is too large
Load Diff
6947
language-de.cpp
6947
language-de.cpp
File diff suppressed because it is too large
Load Diff
8767
language-pl.cpp
8767
language-pl.cpp
File diff suppressed because it is too large
Load Diff
9034
language-ru.cpp
9034
language-ru.cpp
File diff suppressed because it is too large
Load Diff
6014
language-tr.cpp
6014
language-tr.cpp
File diff suppressed because it is too large
Load Diff
52
language.cpp
52
language.cpp
|
@ -52,6 +52,12 @@ struct fullnoun {
|
|||
noun n[NUMLAN-1];
|
||||
};
|
||||
|
||||
#ifdef NOTRANS
|
||||
#define NUMEXTRA 3
|
||||
const char* natchars[NUMEXTRA] = {"°","é","á"};
|
||||
#endif
|
||||
|
||||
#ifndef NOTRANS
|
||||
#include "language-data.cpp"
|
||||
|
||||
hashcode langhash(const string& s) {
|
||||
|
@ -75,6 +81,7 @@ template<class T> const T* findInHashTableS(string s, const T *table, int size)
|
|||
}
|
||||
|
||||
#define findInHashTable(s,t) findInHashTableS(s, t, sizeof(t) / sizeof(t[0]))
|
||||
#endif
|
||||
|
||||
string choose3(int g, string a, string b, string c) {
|
||||
if(g == GEN_M || g == GEN_O) return a;
|
||||
|
@ -100,11 +107,12 @@ set<string> warnshown;
|
|||
|
||||
void basicrep(string& x) {
|
||||
|
||||
const sentence *s = findInHashTable(x, all_sentences);
|
||||
if(!s && !warnshown.count(x)) {
|
||||
printf("WARNING: no translations for '%s'\n", x.c_str());
|
||||
warnshown.insert(x);
|
||||
}
|
||||
#ifndef NOTRANS
|
||||
const sentence *s = findInHashTable(x, all_sentences);
|
||||
if(!s && !warnshown.count(x)) {
|
||||
printf("WARNING: no translations for '%s'\n", x.c_str());
|
||||
warnshown.insert(x);
|
||||
}
|
||||
|
||||
int l = lang();
|
||||
if(l) {
|
||||
|
@ -122,9 +130,11 @@ void basicrep(string& x) {
|
|||
rep(x, "%l0", choose3(playergender(), "l", "la", "lo"));
|
||||
rep(x, "%d0", choose3(playergender(), "", "a", "o"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void parrep(string& x, string w, stringpar p) {
|
||||
#ifndef NOTRANS
|
||||
int l = lang();
|
||||
const fullnoun *N = findInHashTable(p.v, all_nouns);
|
||||
if(l == 1) {
|
||||
|
@ -176,6 +186,7 @@ void parrep(string& x, string w, stringpar p) {
|
|||
rep(x, "%ůj"+w, choose4(N->n[2].genus, "ého", "ou", "é", "ůj"));
|
||||
rep(x, "%ým"+w, choose3(N->n[2].genus, "ým", "ou", "ým"));
|
||||
rep(x, "%ho"+w, choose3(N->n[2].genus, "ho", "ji", "ho"));
|
||||
rep(x, "%ého"+w, choose3(N->n[2].genus, "ého", "ou", "ého"));
|
||||
|
||||
if(p.v == "Mirror Image")
|
||||
rep(x, "%s"+w, "se");
|
||||
|
@ -198,6 +209,7 @@ void parrep(string& x, string w, stringpar p) {
|
|||
rep(x, "%E"+w, choose3(N->n[3].genus, "", "а", "о"));
|
||||
rep(x, "%A"+w, choose3(N->n[3].genus, "ый", "ая", "ое"));
|
||||
rep(x, "%c"+w, choose3(N->n[3].genus, "ся", "ась", ""));
|
||||
rep(x, "%y"+w, choose3(N->n[3].genus, "ый", "ая", "ое"));
|
||||
}
|
||||
else {
|
||||
rep(x,"%"+w,p.v);
|
||||
|
@ -228,10 +240,21 @@ void parrep(string& x, string w, stringpar p) {
|
|||
rep(x, "%den"+w, "the");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(true) {
|
||||
// proper names (R'Lyeh)
|
||||
rep(x,"%"+w,p.v);
|
||||
if(N && (N->english_grammar_flags & 1)) {
|
||||
#ifdef NOTRANS
|
||||
int flags = 0;
|
||||
if(p.v == "R'Lyeh" || p.v == "Camelot") flags = 1;
|
||||
if(p.v == "Crossroads" || p.v == "Crossroads II" ||
|
||||
p.v == "Crossroads III" || p.v == "Crossroads IV" ||
|
||||
p.v == "Kraken Depths" || p.v == "Elemental Planes")
|
||||
flags = 2;
|
||||
#else
|
||||
int flags = N ? N->english_grammar_flags : 0;
|
||||
#endif
|
||||
if(flags & 1) {
|
||||
rep(x,"%the"+w, p.v);
|
||||
rep(x,"%The"+w, p.v);
|
||||
}
|
||||
|
@ -242,7 +265,7 @@ void parrep(string& x, string w, stringpar p) {
|
|||
rep(x,"%his"+w, princessgender() ? "her" : "his");
|
||||
}
|
||||
// plural names (Crossroads)
|
||||
if(N && (N->english_grammar_flags & 2))
|
||||
if(flags & 2)
|
||||
rep(x,"%s"+w, "");
|
||||
else
|
||||
rep(x,"%s"+w, "s");
|
||||
|
@ -288,20 +311,35 @@ string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4) {
|
|||
postrep(x);
|
||||
return x;
|
||||
}
|
||||
string XLAT(string x, stringpar p1, stringpar p2, stringpar p3, stringpar p4, stringpar p5) {
|
||||
basicrep(x);
|
||||
parrep(x,"1",p1.v);
|
||||
parrep(x,"2",p2.v);
|
||||
parrep(x,"3",p3.v);
|
||||
parrep(x,"4",p4.v);
|
||||
parrep(x,"5",p5.v);
|
||||
postrep(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
string XLATN(string x) {
|
||||
#ifndef NOTRANS
|
||||
if(lang()) {
|
||||
const fullnoun *N = findInHashTable(x, all_nouns);
|
||||
if(N) return N->n[lang()-1].nomp;
|
||||
}
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
string XLAT1(string x) {
|
||||
#ifndef NOTRANS
|
||||
if(lang()) {
|
||||
const fullnoun *N = findInHashTable(x, all_nouns);
|
||||
if(N) return N->n[lang()-1].nom;
|
||||
}
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
|
|
400
mapeditor.cpp
400
mapeditor.cpp
|
@ -12,14 +12,16 @@
|
|||
#endif
|
||||
|
||||
namespace mapeditor {
|
||||
#ifndef MOBILE
|
||||
cell *modelcell[200];
|
||||
int subcanvas;
|
||||
#ifndef NOEDIT
|
||||
map<int, cell*> modelcell;
|
||||
|
||||
void clearModelCells() {
|
||||
for(int i=0; i<200; i++) modelcell[i] = NULL;
|
||||
modelcell.clear();
|
||||
}
|
||||
|
||||
void applyModelcell(cell *c) {
|
||||
if(mapeditor::whichPattern == 'H') return;
|
||||
if(mapeditor::whichPattern == 'H') return;
|
||||
int i = realpattern(c);
|
||||
cell *c2 = modelcell[i];
|
||||
|
@ -38,7 +40,7 @@ namespace mapeditor {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef MOBILE
|
||||
#ifndef NOEDIT
|
||||
namespace mapstream {
|
||||
std::map<cell*, int> cellids;
|
||||
vector<cell*> cellbyid;
|
||||
|
@ -83,7 +85,7 @@ namespace mapstream {
|
|||
cellids[c->mov[j]] < i) {
|
||||
int32_t i = cellids[c->mov[j]];
|
||||
save(i);
|
||||
saveChar(c->spn[j]);
|
||||
saveChar(c->spn(j));
|
||||
saveChar(j);
|
||||
break;
|
||||
}
|
||||
|
@ -167,7 +169,7 @@ namespace mapstream {
|
|||
// printf("%p:%d,%d -> %p\n", c2, dir, c);
|
||||
|
||||
// spinval becomes xspinval
|
||||
rspin = (c2->spn[dir] - loadChar() + 42) % c->type;
|
||||
rspin = (c2->spn(dir) - loadChar() + 42) % c->type;
|
||||
}
|
||||
|
||||
cellbyid.push_back(c);
|
||||
|
@ -251,7 +253,7 @@ namespace mapstream {
|
|||
ds.list.push_back(loadPoint());
|
||||
}
|
||||
|
||||
saveImages();
|
||||
buildpolys();
|
||||
bfs();
|
||||
restartGraph();
|
||||
return true;
|
||||
|
@ -302,6 +304,8 @@ namespace mapeditor {
|
|||
case 'z': {
|
||||
int t = zebra40(c);
|
||||
|
||||
if(euclid) return (t*4) % 6;
|
||||
|
||||
int t4 = t>>2, tcdir = 0;
|
||||
|
||||
if(purehepta) tcdir = t^1;
|
||||
|
@ -321,6 +325,7 @@ namespace mapeditor {
|
|||
|
||||
case 'f': {
|
||||
int t = emeraldval(c);
|
||||
if(euclid) return 0;
|
||||
int tcdir = 0, tbest = (t&3);
|
||||
for(int i=0; i<c->type; i++) {
|
||||
cell *c2 = c->mov[i];
|
||||
|
@ -386,7 +391,31 @@ namespace mapeditor {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef MOBILE
|
||||
string infix;
|
||||
|
||||
bool hasInfix(const string &s) {
|
||||
if(infix == "") return true;
|
||||
string t = "";
|
||||
for(int i=0; i<size(s); i++) {
|
||||
char c = s[i];
|
||||
char tt = 0;
|
||||
if(c >= 'a' && c <= 'z') tt += c - 32;
|
||||
else if(c >= 'A' && c <= 'Z') tt += c;
|
||||
if(tt) t += tt;
|
||||
}
|
||||
return t.find(infix) != string::npos;
|
||||
}
|
||||
|
||||
bool editInfix(int uni) {
|
||||
if(uni >= 'A' && uni <= 'Z') infix += uni;
|
||||
else if(uni >= 'a' && uni <= 'z') infix += uni-32;
|
||||
else if(infix != "" && uni == 8) infix = infix.substr(0, size(infix)-1);
|
||||
else if(infix != "" && uni != 0) infix = "";
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef NOEDIT
|
||||
int paintwhat = 0;
|
||||
int painttype = 0;
|
||||
int radius = 0;
|
||||
|
@ -397,11 +426,8 @@ namespace mapeditor {
|
|||
|
||||
bool symRotation, sym01, sym02, sym03;
|
||||
int displaycodes;
|
||||
int subcanvas;
|
||||
int whichpart;
|
||||
|
||||
string infix;
|
||||
|
||||
cell *drawcell;
|
||||
|
||||
const char *mapeditorhelp =
|
||||
|
@ -508,12 +534,6 @@ namespace mapeditor {
|
|||
return 0x20;
|
||||
}
|
||||
|
||||
int colorhistory[10] = {
|
||||
0x202020, 0x800000, 0x008000, 0x000080,
|
||||
0x404040, 0xC0C0C0, 0x804000, 0xC0C000,
|
||||
0x408040, 0xFFD500
|
||||
}, lch;
|
||||
|
||||
bool choosefile = false;
|
||||
bool editext = false;
|
||||
|
||||
|
@ -581,89 +601,23 @@ namespace mapeditor {
|
|||
}
|
||||
}
|
||||
|
||||
void drawColorDialog(int color) {
|
||||
for(int j=0; j<10; j++) {
|
||||
int x = vid.xres / 2 + vid.fsize * 2 * (j-5);
|
||||
int y = vid.yres / 2- 5 * vid.fsize;
|
||||
|
||||
string s0 = ""; s0 += ('q'+j);
|
||||
|
||||
displayColorButton(x, y, s0, 'q'+j, 0, 0, colorhistory[j]);
|
||||
}
|
||||
|
||||
for(int i=0; i<3; i++) for(int j=0; j<16; j++) {
|
||||
int x = vid.xres / 2 + vid.fsize * 2 * (j-8);
|
||||
int y = vid.yres / 2 + (i-1) * vid.fsize * 2;
|
||||
|
||||
int p = color;
|
||||
p &= ~ (0xFF << (8*i));
|
||||
p |= (17*j) << (8*i);
|
||||
|
||||
char c0 = "0aA" [i]+j;
|
||||
string s0 = ""; s0 += c0;
|
||||
|
||||
displayColorButton(x, y, s0, c0, 0, 0, p);
|
||||
}
|
||||
|
||||
displayColorButton(vid.xres/2, vid.yres/2+vid.fsize * 4, "select this color", ' ', 8, 0, color);
|
||||
}
|
||||
|
||||
// 0: nothing happened, 1: color accepted, 2: break
|
||||
int handleKeyColor(int uni, int& color) {
|
||||
int i = 3;
|
||||
int j = 0;
|
||||
if(uni >= '0' && uni <= '0'+15)
|
||||
i=0, j=uni-'0';
|
||||
if(uni >= 'a' && uni <= 'a'+15)
|
||||
i=1, j=uni-'a';
|
||||
if(uni >= 'A' && uni <= 'A'+15)
|
||||
i=2, j=uni-'A';
|
||||
|
||||
if(i<3) {
|
||||
color &= ~ (0xFF << (8*i));
|
||||
color |= (17*j) << (8*i);
|
||||
}
|
||||
else if(uni == ' ') {
|
||||
bool inHistory = false;
|
||||
for(int i=0; i<10; i++) if(colorhistory[i] == paintwhat)
|
||||
inHistory = true;
|
||||
if(!inHistory) { colorhistory[lch] = paintwhat; lch++; lch %= 10; }
|
||||
return 1;
|
||||
}
|
||||
else if(uni >= 'q' && uni <= 'z') {
|
||||
color = colorhistory[uni - 'q'];
|
||||
return 1;
|
||||
}
|
||||
else if(uni) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void displayFunctionKeys() {
|
||||
int fs = vid.fsize + 5;
|
||||
displayButton(8, vid.yres-8-fs*10, XLAT("F1 = help"), SDLK_F1, 0);
|
||||
displayButton(8, vid.yres-8-fs*9, XLAT("F2 = save"), SDLK_F2, 0);
|
||||
displayButton(8, vid.yres-8-fs*8, XLAT("F3 = load"), SDLK_F3, 0);
|
||||
displayButton(8, vid.yres-8-fs*7, XLAT("F4 = file"), SDLK_F3, 0);
|
||||
displayButton(8, vid.yres-8-fs*6, XLAT("F5 = restart"), SDLK_F5, 0);
|
||||
displayButton(8, vid.yres-8-fs*5, XLAT("F6 = HQ shot"), SDLK_F6, 0);
|
||||
displayButton(8, vid.yres-8-fs*4, XLAT("F7 = player on/off"), SDLK_F7, 0);
|
||||
displayButton(8, vid.yres-8-fs*11, XLAT("F1 = help"), SDLK_F1, 0);
|
||||
displayButton(8, vid.yres-8-fs*10, XLAT("F2 = save"), SDLK_F2, 0);
|
||||
displayButton(8, vid.yres-8-fs*9, XLAT("F3 = load"), SDLK_F3, 0);
|
||||
displayButton(8, vid.yres-8-fs*8, XLAT("F4 = file"), SDLK_F3, 0);
|
||||
displayButton(8, vid.yres-8-fs*7, XLAT("F5 = restart"), SDLK_F5, 0);
|
||||
displayButton(8, vid.yres-8-fs*6, XLAT("F6 = HQ shot"), SDLK_F6, 0);
|
||||
displayButton(8, vid.yres-8-fs*5, XLAT("F7 = player on/off"), SDLK_F7, 0);
|
||||
displayButton(8, vid.yres-8-fs*4, XLAT("F8 = SVG shot"), SDLK_F8, 0);
|
||||
displayButton(8, vid.yres-8-fs*3, XLAT("SPACE = map/graphics"), ' ', 0);
|
||||
displayButton(8, vid.yres-8-fs*2, XLAT("ESC = return to the game"), SDLK_ESCAPE, 0);
|
||||
}
|
||||
|
||||
void vpush(int i, const char *name) {
|
||||
string s = XLATN(name);
|
||||
if(infix != "") {
|
||||
string t = "";
|
||||
for(int i=0; i<size(s); i++) {
|
||||
char c = s[i];
|
||||
char tt = 0;
|
||||
if(c >= 'a' && c <= 'z') tt += c - 32;
|
||||
else if(c >= 'A' && c <= 'Z') tt += c;
|
||||
if(tt) t += tt;
|
||||
}
|
||||
if(t.find(infix) == string::npos) return;
|
||||
}
|
||||
if(!hasInfix(s)) return;
|
||||
v.push_back(make_pair(s, i));
|
||||
}
|
||||
|
||||
|
@ -672,42 +626,59 @@ namespace mapeditor {
|
|||
if(choosefile) { drawFileDialog(); return; }
|
||||
|
||||
if(subscreen == 2) {
|
||||
displayStat(2, XLAT("Emerald Pattern"), ONOFF(whichPattern == 'f'), 'f');
|
||||
displayStat(3, XLAT("Palace Pattern"), ONOFF(whichPattern == 'p'), 'p');
|
||||
displayStat(4, XLAT("Zebra Pattern"), ONOFF(whichPattern == 'z'), 'z');
|
||||
dialog::init();
|
||||
|
||||
dialog::addBoolItem(XLAT(euclid ? "three colors" : "Emerald Pattern"), (whichPattern == 'f'), 'f');
|
||||
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == 'p'), 'p');
|
||||
dialog::addBoolItem(XLAT(euclid ? "three colors rotated" : "Zebra Pattern"), (whichPattern == 'z'), 'z');
|
||||
dialog::addBoolItem(XLAT("field pattern"), (whichPattern == 'F'), 'F');
|
||||
|
||||
if(whichPattern == 'f') symRotation = true;
|
||||
displayStat(6, XLAT("rotational symmetry"), ONOFF(symRotation), '0');
|
||||
displayStat(7, XLAT("symmetry 0-1"), ONOFF(sym01), '1');
|
||||
displayStat(8, XLAT("symmetry 0-2"), ONOFF(sym02), '2');
|
||||
displayStat(9, XLAT("symmetry 0-3"), ONOFF(sym03), '3');
|
||||
if(whichPattern == 'F') ;
|
||||
else if(!euclid) {
|
||||
dialog::addBoolItem(XLAT("rotational symmetry"), (symRotation), '0');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-1"), (sym01), '1');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-2"), (sym02), '2');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-3"), (sym03), '3');
|
||||
}
|
||||
else
|
||||
dialog::addBoolItem(XLAT("edit all three colors"), (symRotation), '0');
|
||||
|
||||
displayStat(11, XLAT("display pattern codes (full)"), ONOFF(displaycodes), 'd');
|
||||
displayStat(12, XLAT("display pattern codes (simplified)"), ONOFF(displaycodes), 's');
|
||||
dialog::addBoolItem(XLAT("display pattern codes (full)"), (displaycodes == 1), 'd');
|
||||
dialog::addBoolItem(XLAT("display pattern codes (simplified)"), (displaycodes == 2), 's');
|
||||
|
||||
displayStat(14, XLAT("display only hexagons"), ONOFF(whichShape == '6'), '6');
|
||||
displayStat(15, XLAT("display only heptagons"), ONOFF(whichShape == '7'), '7');
|
||||
displayStat(16, XLAT("display the triheptagonal grid"), ONOFF(whichShape == '8'), '8');
|
||||
dialog::addBoolItem(XLAT("display only hexagons"), (whichShape == '6'), '6');
|
||||
dialog::addBoolItem(XLAT("display only heptagons"), (whichShape == '7'), '7');
|
||||
dialog::addBoolItem(XLAT("display the triheptagonal grid"), (whichShape == '8'), '8');
|
||||
|
||||
displayStat(18, XLAT("predesigned patterns"), "", 'r');
|
||||
dialog::addItem(XLAT("predesigned patterns"), 'r');
|
||||
dialog::display();
|
||||
}
|
||||
else if(subscreen == 3) {
|
||||
displayStat(2, XLAT("Gameboard"), "", 'g');
|
||||
displayStat(3, XLAT("random colors"), "", 'r');
|
||||
displayStat(4, XLAT("rainbow landscape"), "", 'l');
|
||||
dialog::init("predesigned patterns");
|
||||
dialog::addItem(XLAT("Gameboard"), 'g');
|
||||
dialog::addItem(XLAT("random colors"), 'r');
|
||||
dialog::addItem(XLAT("rainbow landscape"), 'l');
|
||||
|
||||
displayStat(6, XLAT("emerald pattern"), "emerald", 'e');
|
||||
dialog::addSelItem(XLAT("emerald pattern"), "emerald", 'e');
|
||||
|
||||
displayStat(8, XLAT("four elements"), "palace", 'b');
|
||||
displayStat(9, XLAT("eight domains"), "palace", 'a');
|
||||
dialog::addSelItem(XLAT("four elements"), "palace", 'b');
|
||||
dialog::addSelItem(XLAT("eight domains"), "palace", 'a');
|
||||
|
||||
displayStat(11, XLAT("zebra pattern"), "zebra", 'z');
|
||||
displayStat(12, XLAT("three stripes"), "zebra", 'x');
|
||||
dialog::addSelItem(XLAT("zebra pattern"), "zebra", 'z');
|
||||
dialog::addSelItem(XLAT("four triangles"), "zebra", 't');
|
||||
dialog::addSelItem(XLAT("three stripes"), "zebra", 'x');
|
||||
|
||||
displayStat(15, XLAT("random black-and-white"), "current", 'w');
|
||||
dialog::addSelItem(XLAT("random black-and-white"), "current", 'w');
|
||||
|
||||
dialog::addSelItem(XLAT("field pattern C"), "field", 'C');
|
||||
dialog::addSelItem(XLAT("field pattern D"), "field", 'D');
|
||||
dialog::addSelItem(XLAT("field pattern N"), "field", 'N');
|
||||
dialog::addSelItem(XLAT("field pattern S"), "field", 'S');
|
||||
dialog::display();
|
||||
}
|
||||
else if(subscreen == 1 && painttype == 6)
|
||||
drawColorDialog(paintwhat);
|
||||
dialog::drawColorDialog(paintwhat);
|
||||
else if(subscreen == 1) {
|
||||
v.clear();
|
||||
if(painttype == 4) painttype = 0;
|
||||
|
@ -810,11 +781,12 @@ namespace mapeditor {
|
|||
createMov(c1, i);
|
||||
int i0 = (42+cf*i+d1) % c1->type;
|
||||
int i1 = (i + d2) % c2->type;
|
||||
spillCopy(c1->mov[i0], c1->spn[i0], c2->mov[i1], c2->spn[i1], r-1);
|
||||
spillCopy(c1->mov[i0], c1->spn(i0), c2->mov[i1], c2->spn(i1), r-1);
|
||||
}
|
||||
}
|
||||
|
||||
int subpatternEmerald(int i) {
|
||||
if(euclid) return (symRotation && (i<3)) ? 0 : i;
|
||||
if((sym01?1:0)+(sym02?1:0)+(sym03?1:0) >= 2) i &= ~3;
|
||||
if(sym01 && (i&1)) i ^= 1;
|
||||
if(sym02 && (i&2)) i ^= 2;
|
||||
|
@ -823,6 +795,7 @@ namespace mapeditor {
|
|||
}
|
||||
|
||||
int subpatternZebra(int i) {
|
||||
if(euclid) return (symRotation && (i<3)) ? 0 : i;
|
||||
i = subpatternEmerald(i);
|
||||
if(symRotation) {
|
||||
if(i >= 8 && i < 12) i -= 4;
|
||||
|
@ -836,6 +809,7 @@ namespace mapeditor {
|
|||
}
|
||||
|
||||
int subpatternPalace(int i) {
|
||||
if(euclid) return i;
|
||||
i = subpatternEmerald(i);
|
||||
if(symRotation && i >= 3) i -= ((i/4-1) % 7) * 4;
|
||||
return i;
|
||||
|
@ -854,8 +828,12 @@ namespace mapeditor {
|
|||
if(polarb50(c)) i|=2;
|
||||
return subpatternPalace(i);
|
||||
}
|
||||
case 'P':
|
||||
return fiftyval(c);
|
||||
case 'H':
|
||||
return realpattern(c);
|
||||
case 'F':
|
||||
return realpattern(c);
|
||||
}
|
||||
return nopattern(c);
|
||||
}
|
||||
|
@ -875,10 +853,19 @@ namespace mapeditor {
|
|||
}
|
||||
case 'H':
|
||||
return towerval(c);
|
||||
case 'F': {
|
||||
pair<int, bool> p = fieldpattern::fieldval(c);
|
||||
return 10*p.first + (p.second?6:7);
|
||||
}
|
||||
}
|
||||
return nopattern(c);
|
||||
}
|
||||
|
||||
int realpatternsh(cell *c) {
|
||||
if(whichPattern == 'F') return nopattern(c);
|
||||
else return realpattern(c);
|
||||
}
|
||||
|
||||
int cellShapeGroup() {
|
||||
if(whichPattern == 'f') return 4;
|
||||
if(whichPattern == 'p') return 5;
|
||||
|
@ -939,6 +926,8 @@ namespace mapeditor {
|
|||
break;
|
||||
case 1:
|
||||
c->item = eItem(paintwhat);
|
||||
if(c->item == itBabyTortoise)
|
||||
tortoise::babymap[c] = getBits(c) ^ tortoise::getRandomBits();
|
||||
break;
|
||||
case 2: {
|
||||
eLand last = c->land;
|
||||
|
@ -980,7 +969,7 @@ namespace mapeditor {
|
|||
case 6:
|
||||
c->land = laCanvas;
|
||||
c->wall = waNone;
|
||||
c->landparam = paintwhat;
|
||||
c->landparam = paintwhat >> 8;
|
||||
break;
|
||||
case 4:
|
||||
c->wall = copywhat->wall;
|
||||
|
@ -995,7 +984,7 @@ namespace mapeditor {
|
|||
break;
|
||||
}
|
||||
checkUndo();
|
||||
if(r) for(int i=0; i<c->type; i++) spill(createMov(c, i), r-1, c->spn[i]);
|
||||
if(r) for(int i=0; i<c->type; i++) spill(createMov(c, i), r-1, c->spn(i));
|
||||
}
|
||||
|
||||
void allInPattern(cell *c, int r, int cdir) {
|
||||
|
@ -1073,11 +1062,11 @@ namespace mapeditor {
|
|||
return true;
|
||||
}
|
||||
|
||||
void handleKey(int uni, int sym) {
|
||||
if(choosefile && handleKeyFile(uni, sym)) ;
|
||||
void handleKey(int sym, int uni) {
|
||||
if(choosefile && handleKeyFile(sym, uni)) ;
|
||||
else if(subscreen == 1 && painttype == 6) {
|
||||
paintwhat_str = "paint";
|
||||
int v = handleKeyColor(uni, paintwhat);
|
||||
int v = dialog::handleKeyColor(sym, uni, paintwhat);
|
||||
if(v == 1) subscreen = 0;
|
||||
if(v == 2) cmode = emNormal;
|
||||
}
|
||||
|
@ -1090,14 +1079,12 @@ namespace mapeditor {
|
|||
subscreen = 0;
|
||||
mousepressed = false;
|
||||
}
|
||||
if(uni >= 'A' && uni <= 'Z') infix += uni;
|
||||
else if(uni >= 'a' && uni <= 'z') infix += uni-32;
|
||||
else if(infix != "" && uni == 8) infix = infix.substr(0, size(infix)-1);
|
||||
else if(infix != "" && uni != 0) infix = "";
|
||||
else if(subscreen == 1 && uni != 0) cmode = emNormal;
|
||||
if(editInfix(uni)) ;
|
||||
else if(subscreen == 1 && uni != 0) cmode = emNormal;
|
||||
}
|
||||
else if(subscreen == 3) {
|
||||
if(uni >= 'a' && uni <= 'z') {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if((uni >= 'a' && uni <= 'z') || (uni >= 'A' && uni <= 'Z')) {
|
||||
whichCanvas = uni;
|
||||
subcanvas = rand();
|
||||
firstland = laCanvas; randomPatternsMode = false;
|
||||
|
@ -1106,7 +1093,8 @@ namespace mapeditor {
|
|||
else if(uni != 0) subscreen = 0;
|
||||
}
|
||||
else if(subscreen == 2) {
|
||||
if(uni == 'f' || uni == 'p' || uni == 'z' || uni == 'H') {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 'f' || uni == 'p' || uni == 'z' || uni == 'H' || uni == 'F') {
|
||||
if(whichPattern == uni) whichPattern = 0;
|
||||
else whichPattern = uni;
|
||||
clearModelCells();
|
||||
|
@ -1171,6 +1159,9 @@ namespace mapeditor {
|
|||
else if(sym == SDLK_F6) {
|
||||
saveHighQualityShot();
|
||||
}
|
||||
else if(sym == SDLK_F8) {
|
||||
svg::render();
|
||||
}
|
||||
else if(sym == SDLK_F7) {
|
||||
drawplayer = !drawplayer;
|
||||
}
|
||||
|
@ -1214,7 +1205,7 @@ namespace mapeditor {
|
|||
|
||||
int dslayer;
|
||||
bool coloring;
|
||||
int colortouse = 0xC0C0C0;
|
||||
int colortouse = 0xC0C0C0FF;
|
||||
|
||||
transmatrix drawtrans;
|
||||
|
||||
|
@ -1255,27 +1246,27 @@ namespace mapeditor {
|
|||
|
||||
void drawGrid() {
|
||||
if(cmode == emDraw && !inHighQual) {
|
||||
lalpha = 0x20;
|
||||
|
||||
for(int d=0; d<84; d++) {
|
||||
transmatrix d2 = drawtrans * rgpushxto0(ccenter);
|
||||
int lalpha;
|
||||
if(d % (84/drawcell->type) == 0)
|
||||
lalpha = 0x40;
|
||||
else
|
||||
lalpha = 0x20;
|
||||
queueline(d2 * C0, d2 * spin(M_PI*d/42)* xpush(1) * C0, 0xC0C0C0);
|
||||
int col = darkena(0xC0C0C0, 0, lalpha);
|
||||
queueline(d2 * C0, d2 * spin(M_PI*d/42)* xpush(1) * C0, col);
|
||||
for(int u=2; u<=20; u++) {
|
||||
if(u % 5 == 0) lalpha = 0x40;
|
||||
else lalpha = 0x20;
|
||||
queueline(
|
||||
d2 * spin(M_PI*d/42)* xpush(u/20.) * C0,
|
||||
d2 * spin(M_PI*(d+1)/42)* xpush(u/20.) * C0,
|
||||
0xC0C0C0);
|
||||
darkena(0xC0C0C0, 0, lalpha));
|
||||
}
|
||||
}
|
||||
queueline(drawtrans*ccenter, drawtrans*coldcenter, 0xC0C0C0);
|
||||
queueline(drawtrans*ccenter, drawtrans*coldcenter, darkena(0xC0C0C0, 0, 0x20));
|
||||
|
||||
lalpha = 0xFF;
|
||||
|
||||
int sg = drawcellShapeGroup();
|
||||
|
||||
for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i) && usershapes[sg][i]) {
|
||||
|
@ -1285,12 +1276,10 @@ namespace mapeditor {
|
|||
for(int a=0; a<size(ds.list); a++) {
|
||||
hyperpoint P2 = drawtrans * ds.list[a];
|
||||
|
||||
int xc, yc, sc;
|
||||
getcoord(P2, xc, yc, sc);
|
||||
queuechr(xc, yc, sc, 10, 'x',
|
||||
a == 0 ? 0x00FF00 :
|
||||
queuechr(P2, 10, 'x',
|
||||
darkena(a == 0 ? 0x00FF00 :
|
||||
a == size(ds.list)-1 ? 0xFF0000 :
|
||||
0xFFFF00);
|
||||
0xFFFF00, 0, 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1299,7 +1288,7 @@ namespace mapeditor {
|
|||
void showDrawEditor() {
|
||||
|
||||
if(coloring) {
|
||||
drawColorDialog(colortouse);
|
||||
dialog::drawColorDialog(colortouse);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1376,14 +1365,15 @@ namespace mapeditor {
|
|||
displayfr(vid.xres-8, vid.yres-8-fs*6, 2, vid.fsize, XLAT("x: %1", fts4(mh[0])), 0xC0C0C0, 16);
|
||||
displayfr(vid.xres-8, vid.yres-8-fs*5, 2, vid.fsize, XLAT("y: %1", fts4(mh[1])), 0xC0C0C0, 16);
|
||||
displayfr(vid.xres-8, vid.yres-8-fs*4, 2, vid.fsize, XLAT("z: %1", fts4(mh[2])), 0xC0C0C0, 16);
|
||||
|
||||
displayfr(vid.xres-8, vid.yres-8-fs*2, 2, vid.fsize, XLAT("r: %1", fts4(inverse_sinh(sqrt(mh[0]*mh[0]+mh[1]*mh[1])))), 0xC0C0C0, 16);
|
||||
displayfr(vid.xres-8, vid.yres-8-fs*2, 2, vid.fsize, XLAT("r: %1", fts4(hdist0(mh))), 0xC0C0C0, 16);
|
||||
displayfr(vid.xres-8, vid.yres-8-fs, 2, vid.fsize, XLAT("ϕ: %1°", fts4(-atan2(mh[1], mh[0]) * 360 / 2 / M_PI)), 0xC0C0C0, 16);
|
||||
}
|
||||
|
||||
displayFunctionKeys();
|
||||
}
|
||||
|
||||
bool rebuildPolys = false;
|
||||
|
||||
void applyToShape(int sg, int id, int uni, hyperpoint mh) {
|
||||
bool haveshape = usershapes[sg][id];
|
||||
bool xnew = false;
|
||||
|
@ -1402,12 +1392,12 @@ namespace mapeditor {
|
|||
if(uni == 'n' || xnew) {
|
||||
dsCur->list.clear();
|
||||
dsCur->list.push_back(mh);
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
if(uni == 'a' && haveshape) {
|
||||
dsCur->list.push_back(mh);
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
if(uni == 'D') {
|
||||
|
@ -1434,7 +1424,7 @@ namespace mapeditor {
|
|||
i--;
|
||||
}
|
||||
}
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
if(uni == 'T') {
|
||||
|
@ -1446,6 +1436,22 @@ namespace mapeditor {
|
|||
loadShape(sg, id, shPFace, 1, 6);
|
||||
loadShape(sg, id, shFlowerHair, 1, 7); */
|
||||
|
||||
// loadShape(sg, id, shPBody, 1, 0);
|
||||
// loadShape(sg, id, shPHead, 1, 1);
|
||||
|
||||
/* loadShape(sg, id, shReptileFrontFoot, 1, 0);
|
||||
loadShape(sg, id, shReptileRearFoot, 1, 1);
|
||||
loadShape(sg, id, shReptileFrontLeg, 1, 2);
|
||||
loadShape(sg, id, shReptileRearLeg, 1, 3);
|
||||
loadShape(sg, id, shReptileBody, 2, 4);
|
||||
loadShape(sg, id, shReptileHead, 2, 5);
|
||||
loadShape(sg, id, shReptileTail, 2, 6); */
|
||||
|
||||
loadShape(sg, id, shTrylobite, 2, 0);
|
||||
|
||||
/* loadShape(sg, id, shYeti, 2, 0);
|
||||
loadShape(sg, id, shHumanFoot, 1, 1); */
|
||||
|
||||
/* loadShape(sg, id, shYeti, 1, 2);
|
||||
loadShape(sg, id, shRatHead, 1, 3);
|
||||
loadShape(sg, id, shRatTail, 1, 1);
|
||||
|
@ -1463,10 +1469,10 @@ namespace mapeditor {
|
|||
loadShape(3, 1, shTurtleFloor[1], 14, 0); */
|
||||
|
||||
// loadShape(sg, id, shDragonSegment, 2, 0);
|
||||
loadShape(sg, id, shDragonSegment, 2, 1);
|
||||
// loadShape(sg, id, shEyes, 2, 2);
|
||||
|
||||
saveImages();
|
||||
// loadShape(sg, id, shFamiliarHead, 2, 0);
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
if(uni == 'K') {
|
||||
|
@ -1483,10 +1489,12 @@ namespace mapeditor {
|
|||
if(vid.cs.charid&1)
|
||||
loadShape(sg, id, shFemaleDress, 2, 2);
|
||||
|
||||
if(vid.cs.charid&1)
|
||||
/* if(vid.cs.charid&1)
|
||||
loadShape(sg, id, shPrincessDress, 1, 3);
|
||||
else
|
||||
loadShape(sg, id, shPrinceDress, 2, 3);
|
||||
loadShape(sg, id, shPrinceDress, 2, 3); */
|
||||
|
||||
loadShape(sg, id, shRatCape2, 1, 3);
|
||||
|
||||
if(vid.cs.charid&1)
|
||||
loadShape(sg, id, shFemaleHair, 2, 4);
|
||||
|
@ -1498,7 +1506,7 @@ namespace mapeditor {
|
|||
|
||||
// loadShape(sg, id, shWolf, 2, dslayer);
|
||||
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
if(uni == '+') dsCur->rots++;
|
||||
|
@ -1506,20 +1514,20 @@ namespace mapeditor {
|
|||
if(uni >= '1' && uni <= '9') {
|
||||
dsCur->rots = uni - '0';
|
||||
if(dsCur->rots == 9) dsCur->rots = 21;
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
if(uni == '0') {
|
||||
dsCur->sym = !dsCur->sym;
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
if(uni == 't') {
|
||||
dsCur->shift = mh;
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
if(uni == 'y') {
|
||||
dsCur->spin = mh;
|
||||
saveImages();
|
||||
rebuildPolys = true;
|
||||
}
|
||||
|
||||
#define COLORKEY (-10000)
|
||||
|
@ -1546,12 +1554,12 @@ namespace mapeditor {
|
|||
return XLAT("vector graphics editor");
|
||||
}
|
||||
|
||||
void drawHandleKey(int uni, int sym, double shiftmul) {
|
||||
void drawHandleKey(int sym, int uni) {
|
||||
|
||||
if(choosefile && handleKeyFile(uni, sym)) return;
|
||||
if(choosefile && handleKeyFile(sym, uni)) return;
|
||||
|
||||
if(coloring) {
|
||||
int v = handleKeyColor(uni, colortouse);
|
||||
int v = dialog::handleKeyColor(sym, uni, colortouse);
|
||||
if(v == 2) { coloring = false; return; }
|
||||
else if(v == 1) { coloring = false; uni = COLORKEY; }
|
||||
else return;
|
||||
|
@ -1581,9 +1589,9 @@ namespace mapeditor {
|
|||
for(int l=0; l<USERLAYERS; l++) if(size(us->d[l].list)) {
|
||||
usershapelayer& ds(us->d[l]);
|
||||
printf("// %d %d %d [%06X]\n", i, j, l, ds.color);
|
||||
for(int i=ds.sh.s; i < ds.sh.e; i++) {
|
||||
printf(" hpcpush(hpxyz(%f,%f,%f));\n", double(hpc[i][0]), double(hpc[i][1]), double(hpc[i][2]));
|
||||
}
|
||||
printf(" ID, %d, %d, ", us->d[l].rots, us->d[l].sym?2:1);
|
||||
for(int i=0; i<size(us->d[l].list); i++)
|
||||
printf("%lf,%lf, ", double(us->d[l].list[i][0]), double(us->d[l].list[i][1]));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
@ -1661,7 +1669,7 @@ namespace mapeditor {
|
|||
fclose(f);
|
||||
addMessage(XLAT("Pictures loaded from %1", picfile));
|
||||
|
||||
saveImages();
|
||||
buildpolys();
|
||||
}
|
||||
|
||||
if(sym == SDLK_F7) {
|
||||
|
@ -1672,6 +1680,10 @@ namespace mapeditor {
|
|||
saveHighQualityShot();
|
||||
}
|
||||
|
||||
if(sym == SDLK_F8) {
|
||||
svg::render();
|
||||
}
|
||||
|
||||
if(sym == SDLK_F5) {
|
||||
for(int i=0; i<USERSHAPEGROUPS; i++)
|
||||
for(int j=0; j<USERSHAPEIDS; j++)
|
||||
|
@ -1688,11 +1700,42 @@ namespace mapeditor {
|
|||
}
|
||||
|
||||
if(sym == SDLK_F10) cmode = emNormal;
|
||||
|
||||
if(rebuildPolys)
|
||||
buildpolys(), rebuildPolys = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
int canvasback = linf[laCanvas].color >> 2;
|
||||
|
||||
int generateCanvas(cell *c) {
|
||||
if(whichCanvas == 'C') {
|
||||
using namespace fieldpattern;
|
||||
int z = fp43.getdist(fieldval(c), make_pair(0,false));
|
||||
if(z < fp43.circrad) return 0x00C000;
|
||||
int z2 = fp43.getdist(fieldval(c), make_pair(fp43.otherpole,false));
|
||||
if(z2 < fp43.disthep[fp43.otherpole] - fp43.circrad)
|
||||
return 0x3000;
|
||||
return 0x6000;
|
||||
}
|
||||
if(whichCanvas == 'D') {
|
||||
using namespace fieldpattern;
|
||||
int z = fp43.getdist(fieldval(c), make_pair(0,false));
|
||||
return 255 * (fp43.maxdist+1-z) / fp43.maxdist;
|
||||
}
|
||||
if(whichCanvas == 'N') {
|
||||
using namespace fieldpattern;
|
||||
int z = fp43.getdist(fieldval(c), make_pair(0,false));
|
||||
int z2 = fp43.getdist(fieldval(c), make_pair(fp43.otherpole,false));
|
||||
if(z < z2) return 0x00C000;
|
||||
if(z > z2) return 0xC00000;
|
||||
return 0xCCCC00;
|
||||
}
|
||||
if(whichCanvas == 'S') {
|
||||
return 0x3F1F0F * fieldpattern::subval(c).second + 0x000080;
|
||||
}
|
||||
if(whichCanvas == 'g')
|
||||
return linf[laCanvas].color >> 2;
|
||||
return canvasback;
|
||||
if(whichCanvas == 'r')
|
||||
return hrand(0xFFFFFF + 1);
|
||||
if(whichCanvas == 'e') {
|
||||
|
@ -1727,6 +1770,12 @@ namespace mapeditor {
|
|||
int fv = zebra40(c);
|
||||
return fcol[fv&3];
|
||||
}
|
||||
if(whichCanvas == 't') {
|
||||
static unsigned int fcol[4] = { 0x804040, 0x408040, 0x404080, 0x808040 };
|
||||
int fv = zebra40(c);
|
||||
if(fv/4 == 4 || fv/4 == 6 || fv/4 == 5 || fv/4 == 10) fv ^= 2;
|
||||
return fcol[fv&3];
|
||||
}
|
||||
if(whichCanvas == 'x') {
|
||||
static unsigned int fcol[4] = { 0xC0C0C0, 0x800000, 0x008000, 0x000080 };
|
||||
return fcol[zebra3(c)];
|
||||
|
@ -1736,20 +1785,17 @@ namespace mapeditor {
|
|||
return fcol[randpattern(c, subcanvas) ? 1 : 0];
|
||||
}
|
||||
if(whichCanvas == 'l') {
|
||||
#ifdef CDATA
|
||||
int col[4];
|
||||
bool err = false;
|
||||
for(int j=0; j<4; j++) {
|
||||
col[j] = getCdata(c, j);
|
||||
col[j] *= 3;
|
||||
col[j] %= 240;
|
||||
if(col[j] > 120) col[j] = 240 - col[j];
|
||||
if(col[j] < -120) col[j] = -240 - col[j];
|
||||
}
|
||||
return (0x808080 + col[0] + (col[1] << 8) + (col[2] << 16)) >> (err?2:0);
|
||||
#endif
|
||||
int col[4];
|
||||
bool err = false;
|
||||
for(int j=0; j<4; j++) {
|
||||
col[j] = getCdata(c, j);
|
||||
col[j] *= 3;
|
||||
col[j] %= 240;
|
||||
if(col[j] > 120) col[j] = 240 - col[j];
|
||||
if(col[j] < -120) col[j] = -240 - col[j];
|
||||
}
|
||||
return (0x808080 + col[0] + (col[1] << 8) + (col[2] << 16)) >> (err?2:0);
|
||||
}
|
||||
return linf[laCanvas].color >> 2;
|
||||
return canvasback;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
39
netgen.cpp
39
netgen.cpp
|
@ -1,7 +1,7 @@
|
|||
// HyperRogue paper model generator
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
#ifndef MOBILE
|
||||
#ifndef NOMODEL
|
||||
namespace netgen {
|
||||
|
||||
// We need a two-dimensional vector class for this.
|
||||
|
@ -143,7 +143,7 @@ namespace netgen {
|
|||
|
||||
loaded = true;
|
||||
|
||||
if(!created) return;
|
||||
if(!created) { fclose(f); return; }
|
||||
|
||||
for(int i=0; i<CELLS; i++) err = fscanf(f, "%d", &ct[i]);
|
||||
|
||||
|
@ -227,7 +227,7 @@ namespace netgen {
|
|||
polyy[0] = int(v1.y);
|
||||
polyy[1] = int(v2.y);
|
||||
polyy[2] = int(v3.y);
|
||||
filledPolygonColor(s, polyx, polyy, 3, col);
|
||||
filledPolygonColorI(s, polyx, polyy, 3, col);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ namespace netgen {
|
|||
|
||||
int& hqpixel(hyperpoint h) {
|
||||
int hx, hy, hs;
|
||||
getcoord(h, hx, hy, hs);
|
||||
getcoord0(h, hx, hy, hs);
|
||||
return qpixel(hqsurface, hx, hy);
|
||||
}
|
||||
|
||||
|
@ -644,20 +644,25 @@ namespace netgen {
|
|||
nei[i][e] >= 0 ? 0x808080 :
|
||||
0xC0C0C0;
|
||||
|
||||
drawline(hvec(i, (e+ofs)%t), hvec(i, (e+1+ofs)%t), (col << 8) + 0xFF);
|
||||
prettyline(hvec(i, (e+ofs)%t), hvec(i, (e+1+ofs)%t), (col << 8) + 0xFF, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(mode != 2) {
|
||||
displayStat( 2, XLAT("synchronize net and map"), "", 's');
|
||||
displayStat( 3, XLAT("display the scope"), "", 't');
|
||||
displayStat( 5, XLAT("create the model"), "", 'c');
|
||||
displayStat( 7, XLAT("back to HyperRogue"), "", 'q');
|
||||
displayStat( 9, XLAT("design the net"), "", 'd');
|
||||
dialog::init("paper model creator");
|
||||
|
||||
dialog::addItem(XLAT("synchronize net and map"), 's');
|
||||
dialog::addItem(XLAT("display the scope"), 't');
|
||||
dialog::addItem(XLAT("create the model"), 'c');
|
||||
dialog::addItem(XLAT("back to HyperRogue"), 'q');
|
||||
dialog::addItem(XLAT("design the net"), 'd');
|
||||
|
||||
dialog::display();
|
||||
}
|
||||
}
|
||||
|
||||
void handleKey(int uni, int sym) {
|
||||
void handleKey(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(!loaded) {
|
||||
loadData();
|
||||
|
@ -668,7 +673,7 @@ namespace netgen {
|
|||
}
|
||||
if(!created) {
|
||||
View = Id;
|
||||
if(lcenterover) viewctr.h = lcenterover->master;
|
||||
if(centerover) viewctr.h = centerover->master;
|
||||
else viewctr.h = cwt.c->master;
|
||||
playermoved = false;
|
||||
dataFromHR();
|
||||
|
@ -684,17 +689,17 @@ namespace netgen {
|
|||
}
|
||||
if(uni == 's') {
|
||||
View = Id;
|
||||
if(lcenterover) viewctr.h = lcenterover->master;
|
||||
if(centerover) viewctr.h = centerover->master;
|
||||
else viewctr.h = cwt.c->master;
|
||||
playermoved = false;
|
||||
}
|
||||
if(uni == 'c') {
|
||||
else if(uni == 'c') {
|
||||
createPapermodel();
|
||||
addMessage(XLAT("The paper model created as papermodel-*.bmp"));
|
||||
}
|
||||
if(uni == 'd') designNet();
|
||||
if(uni == 't') mode = 2;
|
||||
if(uni == 'q' || sym == SDLK_ESCAPE)
|
||||
else if(uni == 'd') designNet();
|
||||
else if(uni == 't') mode = 2;
|
||||
else if(uni || sym == SDLK_F10)
|
||||
cmode = emNormal;
|
||||
}
|
||||
|
||||
|
|
467
orbs.cpp
467
orbs.cpp
|
@ -17,10 +17,18 @@ bool markEmpathy(eItem it) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool markEmpathy2(eItem it) {
|
||||
if(items[itOrbEmpathy] < 2) return false;
|
||||
if(!markOrb2(it)) return false;
|
||||
markOrb2(itOrbEmpathy);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool markOrb2(eItem it) {
|
||||
if(!items[it]) return false;
|
||||
return markOrb(it);
|
||||
/* if(!items[it]) return false;
|
||||
orbused[it] = true;
|
||||
return items[it] > 1;
|
||||
return items[it] > 1; */
|
||||
}
|
||||
|
||||
int fixpower(int qty) {
|
||||
|
@ -58,32 +66,32 @@ void empathyMove(cell *c, cell *cto, int dir) {
|
|||
}
|
||||
|
||||
bool reduceOrbPower(eItem it, int cap) {
|
||||
if(items[it] && (lastorbused[it] || (it == itOrbShield && items[it]>3) || !markOrb(itOrbPreserve))) {
|
||||
items[it] -= numplayers();
|
||||
if(items[it] && (lastorbused[it] || (it == itOrbShield && items[it]>3) || !markOrb(itOrbTime))) {
|
||||
items[it] -= multi::activePlayers();
|
||||
if(isHaunted(cwt.c->land)) survivalist = false;
|
||||
if(items[it] < 0) items[it] = 0;
|
||||
if(items[it] > cap) items[it] = cap;
|
||||
if(items[it] > cap && timerghost) items[it] = cap;
|
||||
if(items[it] == 0 && it == itOrbLove)
|
||||
princess::bringBack();
|
||||
return true;
|
||||
}
|
||||
if(items[it] > cap) items[it] = cap;
|
||||
if(items[it] > cap && timerghost) items[it] = cap;
|
||||
return false;
|
||||
}
|
||||
|
||||
void reduceOrbPowerAlways(eItem it) {
|
||||
if(items[it]) {
|
||||
items[it] -= numplayers();
|
||||
items[it] -= multi::activePlayers();
|
||||
if(items[it] < 0) items[it] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void reduceOrbPowers() {
|
||||
if(getMount()) markOrb(itOrbDomination);
|
||||
if(haveMount()) markOrb(itOrbDomination);
|
||||
for(int i=0; i<ittypes; i++)
|
||||
lastorbused[i] = orbused[i], orbused[i] = false;
|
||||
if(items[itOrbShield]) orbused[itOrbShield] = lastorbused[itOrbShield];
|
||||
reduceOrbPower(itOrbPreserve, cwt.c->land == laCaribbean ? 777 : 150);
|
||||
reduceOrbPower(itOrbTime, cwt.c->land == laCaribbean ? 777 : 150);
|
||||
if(invismove && !invisfish) markOrb(itOrbInvis);
|
||||
reduceOrbPower(itOrbLightning, 777);
|
||||
reduceOrbPower(itOrbSpeed, 67);
|
||||
|
@ -96,19 +104,20 @@ void reduceOrbPowers() {
|
|||
reduceOrbPower(itOrbDragon, 111);
|
||||
reduceOrbPower(itOrbPsi, 111);
|
||||
reduceOrbPower(itOrbInvis, 77);
|
||||
reduceOrbPower(itOrbGhost, 77);
|
||||
reduceOrbPower(itOrbAether, 77);
|
||||
reduceOrbPower(itOrbDigging, 100);
|
||||
reduceOrbPower(itOrbTeleport, 200);
|
||||
reduceOrbPower(itOrbTelekinesis, 150);
|
||||
reduceOrbPower(itOrbSpace, 150);
|
||||
reduceOrbPowerAlways(itOrbSafety);
|
||||
reduceOrbPower(itOrbThorns, 150);
|
||||
reduceOrbPower(itOrbWater, 150);
|
||||
reduceOrbPower(itOrbAir, 150);
|
||||
reduceOrbPower(itOrbFrog, 77);
|
||||
reduceOrbPower(itOrbDash, 77);
|
||||
reduceOrbPower(itOrbDiscord, 67);
|
||||
reduceOrbPower(itOrbSummon, 333);
|
||||
reduceOrbPower(itOrbMatter, 333);
|
||||
reduceOrbPower(itOrbFish, 77);
|
||||
reduceOrbPower(itOrbFish, 57 + 20 * multi::activePlayers());
|
||||
if(!items[itSavedPrincess]) items[itOrbLove] = 0;
|
||||
reduceOrbPower(itOrbLove, 777);
|
||||
reduceOrbPower(itOrbStunning, 100);
|
||||
|
@ -117,13 +126,21 @@ void reduceOrbPowers() {
|
|||
reduceOrbPower(itOrbFreedom, 77);
|
||||
reduceOrbPower(itOrbEmpathy, 77);
|
||||
markOrb(itOrb37); reduceOrbPower(itOrb37, 333);
|
||||
reduceOrbPower(itOrbSkunk, 77);
|
||||
reduceOrbPower(itOrbBeauty, 77);
|
||||
reduceOrbPower(itOrbEnergy, 77);
|
||||
reduceOrbPower(itOrbDomination, 120);
|
||||
reduceOrbPower(itOrbSword, 100 + 20 * multi::activePlayers());
|
||||
reduceOrbPower(itOrbSword2, 100 + 20 * multi::activePlayers());
|
||||
reduceOrbPower(itOrbStone, 120);
|
||||
reduceOrbPower(itOrbNature, 120);
|
||||
reduceOrbPower(itOrbRecall, 77);
|
||||
reduceOrbPower(itOrbBull, 120);
|
||||
reduceOrbPower(itOrbHorns, 77);
|
||||
if(cwt.c->land != laWildWest)
|
||||
reduceOrbPower(itRevolver, 6);
|
||||
whirlwind::calcdirs(cwt.c);
|
||||
items[itStrongWind] = !items[itOrbGhost] && whirlwind::qdirs == 1 && !euclid;
|
||||
items[itStrongWind] = !items[itOrbAether] && whirlwind::qdirs == 1 && !euclid;
|
||||
items[itWarning] = 0;
|
||||
}
|
||||
|
||||
void flashAlchemist(cell *c) {
|
||||
|
@ -135,11 +152,12 @@ void flashAlchemist(cell *c) {
|
|||
}
|
||||
}
|
||||
|
||||
void flashCell(cell *c, bool msg) {
|
||||
void flashCell(cell *c, eMonster killer, flagtype flags) {
|
||||
eWall ow = c->wall;
|
||||
flashAlchemist(c);
|
||||
if(msg && c->monst && !isWorm(c) && c->monst != moShadow)
|
||||
if((flags & AF_MSG) && c->monst && !isWorm(c) && c->monst != moShadow)
|
||||
addMessage(XLAT("%The1 is destroyed by the Flash.", c->monst));
|
||||
killWithMessage(c, false);
|
||||
if(c->monst || isPlayerOn(c)) attackMonster(c, flags, killer);
|
||||
if(isIcyLand(c))
|
||||
HEAT(c) += 2;
|
||||
if(c->land == laDryForest)
|
||||
|
@ -147,6 +165,7 @@ void flashCell(cell *c, bool msg) {
|
|||
if(c->wall == waCavewall) c->wall = waCavefloor;
|
||||
if(c->wall == waDeadTroll) c->wall = waCavefloor;
|
||||
if(c->wall == waDeadTroll2) c->wall = waNone;
|
||||
if(c->wall == waPetrified) c->wall = waNone;
|
||||
if(c->wall == waDeadfloor2) c->wall = waDeadfloor;
|
||||
if(c->wall == waGargoyleFloor) c->wall = waChasm;
|
||||
if(c->wall == waGargoyleBridge) placeWater(c, c);
|
||||
|
@ -174,26 +193,35 @@ void flashCell(cell *c, bool msg) {
|
|||
eWall w = c->wall;
|
||||
c->wall = waNone;
|
||||
for(int i=0; i<c->type; i++) if(c->mov[i] && c->mov[i]->wall == w)
|
||||
flashCell(c->mov[i], msg);
|
||||
flashCell(c->mov[i], killer, flags);
|
||||
}
|
||||
if(c->wall == waRed1) c->wall = waNone;
|
||||
else if(c->wall == waRed2) c->wall = waRed1;
|
||||
else if(c->wall == waRed3) c->wall = waRed2;
|
||||
|
||||
if(c->wall == waBarrowWall) c->wall = waBarrowDig;
|
||||
else if(c->wall == waBarrowDig) c->wall = waNone;
|
||||
|
||||
if(c->wall != ow && ow) drawParticles(c, winf[ow].color, 16);
|
||||
|
||||
if(hasTimeout(c) && c->wparam < 77) c->wparam = 77;
|
||||
if(isActivable(c))
|
||||
activateActiv(c, false);
|
||||
}
|
||||
|
||||
void activateFlashFrom(cell *cf) {
|
||||
void activateFlashFrom(cell *cf, eMonster who, flagtype flags) {
|
||||
drawFlash(cf);
|
||||
playSound(cf, "storm");
|
||||
for(int i=0; i<size(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
if(c == cf) continue;
|
||||
for(int t=0; t<c->type; t++)
|
||||
for(int u=0; u<cf->type; u++)
|
||||
if(c->mov[t] == cf->mov[u] && c->mov[t] != NULL) {
|
||||
flashCell(c, true);
|
||||
flashCell(c, who, flags);
|
||||
goto nexti;
|
||||
}
|
||||
nexti: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,50 +261,75 @@ void checkFreedom(cell *cf) {
|
|||
}
|
||||
addMessage(XLAT("Your %1 activates!", itOrbFreedom));
|
||||
drainOrb(itOrbFreedom);
|
||||
drawBigFlash(cf);
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
drawBigFlash(playerpos(i));
|
||||
for(int i=0; i<size(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
if(c == cf) continue;
|
||||
if(c == cf && !shmup::on) continue;
|
||||
if(c->cpdist > 5) break;
|
||||
flashCell(c, true);
|
||||
flashCell(c, moPlayer, AF_MAGIC);
|
||||
}
|
||||
}
|
||||
|
||||
void activateFlash() {
|
||||
int tk = tkills();
|
||||
drawFlash(cwt.c);
|
||||
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
drawFlash(playerpos(i));
|
||||
|
||||
addMessage(XLAT("You activate the Flash spell!"));
|
||||
playSound(cwt.c, "storm");
|
||||
drainOrb(itOrbFlash);
|
||||
for(int i=0; i<size(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
if(c->cpdist > 2) break;
|
||||
flashCell(c, false);
|
||||
flashCell(c, moPlayer, AF_MAGIC);
|
||||
}
|
||||
achievement_count("FLASH", tkills(), tk);
|
||||
}
|
||||
|
||||
bool barrierAt(cellwalker& c, int d) {
|
||||
if(d >= 7) return true;
|
||||
if(d <= -7) return true;
|
||||
bool reflectingBarrierAt(cell *c) {
|
||||
return
|
||||
c->wall == waBarrier || c->wall == waCamelot ||
|
||||
c->wall == waPalace || c->wall == waPlatform ||
|
||||
c->wall == waTempWall || c->wall == waWarpGate || c->wall == waBarrowDig || c->wall == waBarrowWall;
|
||||
}
|
||||
|
||||
bool reflectingBarrierAt(cellwalker& c, int d) {
|
||||
if(d >= 3) return true;
|
||||
if(d <= -3) return true;
|
||||
d = c.spin + d + 42;
|
||||
d%=c.c->type;
|
||||
if(!c.c->mov[d]) return true;
|
||||
|
||||
return reflectingBarrierAt(c.c->mov[d]);
|
||||
// WAS:
|
||||
// if(c.c->mov[d]->wall == waBarrier) return true;
|
||||
if(c.c->mov[d]->land == laBarrier || c.c->mov[d]->land == laOceanWall ||
|
||||
c.c->mov[d]->land == laHauntedWall ||
|
||||
c.c->mov[d]->land == laElementalWall) return true;
|
||||
return false;
|
||||
// THEN:
|
||||
// if(c.c->mov[d]->land == laBarrier || c.c->mov[d]->land == laOceanWall ||
|
||||
// c.c->mov[d]->land == laHauntedWall ||
|
||||
// c.c->mov[d]->land == laElementalWall) ;
|
||||
// return false;
|
||||
}
|
||||
|
||||
void killAdjacentSharks(cell *c) {
|
||||
for(int i=0; i<c->type; i++) {
|
||||
cell *c2 = c->mov[i];
|
||||
if(c2 && isShark(c2->monst)) {
|
||||
if(!c2) continue;
|
||||
if(isShark(c2->monst)) {
|
||||
c2->ligon = true;
|
||||
killMonster(c2);
|
||||
killMonster(c2, moLightningBolt);
|
||||
killAdjacentSharks(c2);
|
||||
}
|
||||
if(isKraken(c2->monst) && isWatery(c2)) {
|
||||
cell *c3 = kraken::head(c2);
|
||||
c3->ligon = true;
|
||||
forCellEx(c4, c3) killMonster(c4, moLightningBolt); // kill-all
|
||||
forCellEx(c4, c3) if(isWatery(c4)) {
|
||||
c4->ligon = true;
|
||||
killAdjacentSharks(c4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,20 +346,23 @@ void castLightningBolt(cellwalker lig) {
|
|||
|
||||
cell *c = lig.c;
|
||||
|
||||
eWall ow = c->wall;
|
||||
|
||||
flashAlchemist(c);
|
||||
if(c->monst == moMetalBeast2 && !c->item) c->item = itFulgurite;
|
||||
killWithMessage(c, false);
|
||||
if(c->monst) attackMonster(c, AF_MAGIC, moLightningBolt);
|
||||
if(isIcyLand(c)) HEAT(c) += 2;
|
||||
if(c->land == laDryForest) c->landparam += 2;
|
||||
bool first = !c->ligon;
|
||||
c->ligon = 1;
|
||||
|
||||
bool brk = false, spin = false;
|
||||
|
||||
|
||||
if(c->wall == waGargoyle) brk = true;
|
||||
if(c->wall == waCavewall) c->wall = waCavefloor, brk = true;
|
||||
if(c->wall == waDeadTroll) c->wall = waCavefloor, brk = true;
|
||||
if(c->wall == waDeadTroll2)c->wall = waNone, brk = true;
|
||||
if(c->wall == waPetrified) c->wall = waNone, brk = true;
|
||||
if(c->wall == waDeadfloor2)c->wall = waDeadfloor;
|
||||
if(c->wall == waRubble) c->wall = waNone;
|
||||
if(c->wall == waDeadwall) c->wall = waDeadfloor2, brk = true;
|
||||
|
@ -315,10 +371,17 @@ void castLightningBolt(cellwalker lig) {
|
|||
if(c->wall == waIcewall) c->wall = waNone, brk = true;
|
||||
if(c->wall == waAncientGrave) c->wall = waNone, spin = true;
|
||||
if(c->wall == waFreshGrave) c->wall = waNone, spin = true;
|
||||
|
||||
if(c->wall == waFreshGrave) c->wall = waNone, spin = true;
|
||||
|
||||
if(c->wall == waBigStatue) c->wall = waNone, spin = true;
|
||||
if(c->wall == waColumn) c->wall = waNone, spin = true;
|
||||
if(c->wall == waStone) c->wall = waNone, brk = true;
|
||||
|
||||
if(c->wall == waCanopy || c->wall == waTrunk || c->wall == waBigBush || c->wall == waSmallBush) {
|
||||
makeflame(c, 12, false); brk = true;
|
||||
}
|
||||
|
||||
if(c->wall == waGrounded) brk = true;
|
||||
if(c->wall == waFan) spin = true;
|
||||
if(c->wall == waMetal) c->wall = waCharged, brk = true;
|
||||
|
@ -357,18 +420,22 @@ void castLightningBolt(cellwalker lig) {
|
|||
brk = true;
|
||||
}
|
||||
|
||||
if(c->wall != ow && ow)
|
||||
drawParticles(c, winf[ow].color, 16);
|
||||
|
||||
if(c == cwt.c) {bnc++; if(bnc > 10) break; }
|
||||
if(spin) cwspin(lig, hrand(lig.c->type));
|
||||
|
||||
if(brk) break;
|
||||
|
||||
if(c->wall == waBarrier || c->wall == waCamelot || c->wall == waPalace || c->wall == waPlatform ||
|
||||
c->wall == waTempWall || c->wall == waWarpGate) {
|
||||
if(reflectingBarrierAt(c)) {
|
||||
int left = -1;
|
||||
int right = 1;
|
||||
while(barrierAt(lig, left)) left--;
|
||||
while(barrierAt(lig, right)) right++;
|
||||
cwspin(lig, -(right + left));
|
||||
while(!reflectingBarrierAt(lig, left)) left--;
|
||||
while(!reflectingBarrierAt(lig, right)) right++;
|
||||
cwspin(lig, right + left);
|
||||
if(c->wall == waBarrowWall) c->wall = waBarrowDig;
|
||||
else if(c->wall == waBarrowDig) c->wall = waNone;
|
||||
bnc++; if(bnc > 10) break;
|
||||
}
|
||||
else {
|
||||
|
@ -377,11 +444,13 @@ void castLightningBolt(cellwalker lig) {
|
|||
}
|
||||
|
||||
if(c->wall == waCloud) {
|
||||
drawParticles(c, winf[ow].color, 16);
|
||||
c->wall = waNone;
|
||||
mirror::createMirages(c, lig.spin, moLightningBolt);
|
||||
}
|
||||
|
||||
if(c->wall == waMirror) {
|
||||
drawParticles(c, winf[ow].color, 16);
|
||||
c->wall = waNone;
|
||||
mirror::createMirrors(c, lig.spin, moLightningBolt);
|
||||
break;
|
||||
|
@ -389,6 +458,10 @@ void castLightningBolt(cellwalker lig) {
|
|||
}
|
||||
}
|
||||
|
||||
void castLightningBoltFrom(cell *c) {
|
||||
for(int i=0; i<c->type; i++) castLightningBolt(cellwalker(c, i));
|
||||
}
|
||||
|
||||
void activateLightning() {
|
||||
int tk = tkills();
|
||||
drawLightning();
|
||||
|
@ -397,14 +470,16 @@ void activateLightning() {
|
|||
for(int i=0; i<size(dcal); i++) if(dcal[i]) dcal[i]->ligon = 0;
|
||||
|
||||
drainOrb(itOrbLightning);
|
||||
for(int i=0; i<cwt.c->type; i++)
|
||||
castLightningBolt(cellwalker(cwt.c, i));
|
||||
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
castLightningBoltFrom(playerpos(i));
|
||||
|
||||
elec::afterOrb = true;
|
||||
elec::act();
|
||||
elec::afterOrb = false;
|
||||
|
||||
achievement_count("LIGHTNING", tkills(), tk);
|
||||
playSound(cwt.c, "storm");
|
||||
}
|
||||
|
||||
// roCheck: return orb type if successful, 0 otherwise
|
||||
|
@ -423,11 +498,43 @@ bool haveRangedTarget() {
|
|||
return false;
|
||||
}
|
||||
|
||||
void checkmoveO() {
|
||||
if(multi::players > 1 && multi::activePlayers() == 1)
|
||||
multi::checklastmove();
|
||||
if(multi::players == 1) checkmove();
|
||||
}
|
||||
|
||||
int teleportAction() {
|
||||
// normal teleport
|
||||
if(shmup::on || numplayers() == 1) return 1;
|
||||
// multi-player, but all in -- do nothing
|
||||
else if(numplayers() == multi::activePlayers()) return 0;
|
||||
// otherwise teleport to the game
|
||||
else return 2;
|
||||
}
|
||||
|
||||
void teleportTo(cell *dest) {
|
||||
playSound(dest, "other-teleport");
|
||||
if(dest->monst) {
|
||||
cwt.c->monst = dest->monst;
|
||||
dest->monst = moNone;
|
||||
}
|
||||
|
||||
if(teleportAction() == 2) {
|
||||
bool b = multiRevival(dest, NULL);
|
||||
if(b) {
|
||||
killFriendlyIvy();
|
||||
drainOrb(itOrbTeleport);
|
||||
movecost(cwt.c, dest);
|
||||
playerMoveEffects(cwt.c, dest);
|
||||
for(int i=9; i>=0; i--)
|
||||
setdist(dest, i, NULL);
|
||||
bfs();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
killFriendlyIvy();
|
||||
movecost(cwt.c, dest);
|
||||
playerMoveEffects(cwt.c, dest);
|
||||
cwt.c = dest; cwt.spin = hrand(dest->type); flipplayer = !!(hrand(2));
|
||||
|
@ -441,19 +548,32 @@ void teleportTo(cell *dest) {
|
|||
|
||||
bfs();
|
||||
|
||||
items[itOrbSword] = 0;
|
||||
items[itOrbSword2] = 0;
|
||||
if(shmup::on)
|
||||
shmup::teleported();
|
||||
else
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void jumpTo(cell *dest, eItem byWhat) {
|
||||
void jumpTo(cell *dest, eItem byWhat, int bonuskill = 0, eMonster dashmon = moNone) {
|
||||
if(byWhat != itStrongWind) playSound(dest, "orb-frog");
|
||||
movecost(cwt.c, dest);
|
||||
|
||||
killFriendlyIvy();
|
||||
|
||||
cell *c1 = cwt.c;
|
||||
animateMovement(cwt.c, dest, LAYER_SMALL);
|
||||
cwt.c = dest;
|
||||
forCellIdEx(c2, i, dest) if(c2->cpdist < dest->cpdist) {
|
||||
cwt.spin = i;
|
||||
flipplayer = true;
|
||||
}
|
||||
countLocalTreasure();
|
||||
|
||||
items[itOrbSword] = 0;
|
||||
items[itOrbSword2] = 0;
|
||||
stabbingAttack(c1, dest, moPlayer, bonuskill);
|
||||
playerMoveEffects(c1, dest);
|
||||
if(cwt.c->item != itOrbYendor && cwt.c->item != itHolyGrail)
|
||||
collectItem(cwt.c, true);
|
||||
|
@ -463,6 +583,11 @@ void jumpTo(cell *dest, eItem byWhat) {
|
|||
addMessage(XLAT("You jump!"));
|
||||
}
|
||||
|
||||
if(byWhat == itOrbDash) {
|
||||
useupOrb(itOrbDash, 5);
|
||||
addMessage(XLAT("You vault over %the1!", dashmon));
|
||||
}
|
||||
|
||||
mirror::destroy();
|
||||
|
||||
for(int i=9; i>=0; i--)
|
||||
|
@ -476,6 +601,19 @@ void jumpTo(cell *dest, eItem byWhat) {
|
|||
monstersTurn();
|
||||
}
|
||||
|
||||
void growIvyTo(cell *dest, cell *src) {
|
||||
if(dest->monst)
|
||||
attackMonster(dest, AF_MSG | AF_ORSTUN, moFriendlyIvy);
|
||||
else {
|
||||
dest->monst = moFriendlyIvy;
|
||||
dest->mondir = neighborId(dest, src);
|
||||
moveEffect(dest, src, moFriendlyIvy);
|
||||
empathyMove(src, dest, neighborId(src, dest));
|
||||
}
|
||||
createNoise(1);
|
||||
monstersTurn();
|
||||
}
|
||||
|
||||
void telekinesis(cell *dest) {
|
||||
|
||||
int cost = dest->cpdist * dest->cpdist;
|
||||
|
@ -493,17 +631,17 @@ void telekinesis(cell *dest) {
|
|||
}
|
||||
|
||||
if(dest->wall == waGlass) {
|
||||
drainOrb(itOrbTelekinesis);
|
||||
drainOrb(itOrbSpace);
|
||||
addMessage(XLAT("Your power is drained by %the1!", dest->wall));
|
||||
}
|
||||
|
||||
moveItem(dest, cwt.c, true);
|
||||
collectItem(cwt.c, true);
|
||||
useupOrb(itOrbTelekinesis, cost);
|
||||
useupOrb(itOrbSpace, cost);
|
||||
|
||||
createNoise(3);
|
||||
bfs();
|
||||
if(!shmup::on) checkmove();
|
||||
if(!shmup::on) checkmoveO();
|
||||
}
|
||||
|
||||
eMonster summonedAt(cell *dest) {
|
||||
|
@ -517,7 +655,7 @@ eMonster summonedAt(cell *dest) {
|
|||
if(dest->wall == waAncientGrave || dest->wall == waFreshGrave)
|
||||
return moGhost;
|
||||
if(dest->wall == waClosePlate || dest->wall == waOpenPlate)
|
||||
return moPalace;
|
||||
return dest->land == laPalace ? moPalace : moBat;
|
||||
if(dest->wall == waFloorA || dest->wall == waFloorB)
|
||||
return moSlime;
|
||||
if(dest->wall == waFloorC || dest->wall == waFloorD)
|
||||
|
@ -536,8 +674,11 @@ eMonster summonedAt(cell *dest) {
|
|||
return
|
||||
isElemental(dest->land) ? moWaterElemental :
|
||||
dest->land == laLivefjord ? moViking :
|
||||
dest->land == laGridCoast ? moRatling :
|
||||
dest->land == laKraken ? moViking :
|
||||
dest->land == laWarpCoast ? moRatling :
|
||||
moPirate;
|
||||
if(isReptile(dest->wall))
|
||||
return moReptile;
|
||||
if(dest->wall == waChasm)
|
||||
return moAirElemental;
|
||||
if(isFire(dest))
|
||||
|
@ -561,6 +702,12 @@ eMonster summonedAt(cell *dest) {
|
|||
if(dest->wall == waGiantRug)
|
||||
return moVizier;
|
||||
if(dest->wall == waNone) {
|
||||
if(dest->land == laBull) return moRagingBull;
|
||||
if(dest->land == laPrairie) return moAirElemental;
|
||||
if(dest->land == laZebra) return moAirElemental;
|
||||
if(dest->land == laMirror) return moAirElemental;
|
||||
if(dest->land == laMountain) return moAirElemental; // unfortunately Ivies are too large
|
||||
if(dest->land == laDungeon) return moBat;
|
||||
if(dest->land == laIce) return moFireElemental;
|
||||
if(dest->land == laDesert) return moEarthElemental;
|
||||
if(dest->land == laJungle) return moWaterElemental;
|
||||
|
@ -587,20 +734,24 @@ eMonster summonedAt(cell *dest) {
|
|||
if(dest->land == laWildWest) return moOutlaw;
|
||||
if(dest->land == laClearing) return moForestTroll;
|
||||
if(dest->land == laWhirlwind) return moAirElemental;
|
||||
if(dest->land == laGridCoast) return moRatling;
|
||||
if(dest->land == laWarpCoast) return moRatling;
|
||||
if(dest->land == laRose) return moRoseLady;
|
||||
if(dest->land == laDragon) return moFireElemental;
|
||||
if(dest->land == laTortoise) return moTortoise;
|
||||
if(dest->land == laBurial) return moEarthElemental;
|
||||
if(isHaunted(dest->land)) return moGhost;
|
||||
}
|
||||
return moNone;
|
||||
}
|
||||
|
||||
void summonAt(cell *dest) {
|
||||
playSound(dest, "orb-ranged");
|
||||
dest->monst = summonedAt(dest);
|
||||
dest->stuntime = 3;
|
||||
if(dest->monst == moPirate || dest->monst == moViking || (dest->monst == moRatling && dest->wall == waSea))
|
||||
dest->wall = waBoat;
|
||||
dest->wall = waBoat, dest->item = itNone;
|
||||
if(dest->monst == moViking && dest->land == laKraken)
|
||||
dest->item = itOrbFish;
|
||||
if(dest->wall == waStrandedBoat)
|
||||
dest->wall = waBoat;
|
||||
else if(dest->monst == moWaterElemental)
|
||||
|
@ -620,7 +771,7 @@ void summonAt(cell *dest) {
|
|||
useupOrb(itOrbSummon, 20);
|
||||
createNoise(2);
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
bool tempWallPossibleAt(cell *dest) {
|
||||
|
@ -641,46 +792,61 @@ void tempWallAt(cell *dest) {
|
|||
dest->item = itNone; // underwater items are destroyed by this
|
||||
createNoise(2);
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void psi_attack(cell *dest) {
|
||||
playSound(dest, "other-mind");
|
||||
if(isNonliving(dest->monst))
|
||||
addMessage(XLAT("You destroy %the1 with a mental blast!", dest->monst));
|
||||
else if(isDragon(dest->monst))
|
||||
else if(isDragon(dest->monst) || isKraken(dest->monst))
|
||||
addMessage(XLAT("You damage %the1 with a mental blast!", dest->monst));
|
||||
else
|
||||
addMessage(XLAT("You kill %the1 with a mental blast!", dest->monst));
|
||||
killWithMessage(dest, false);
|
||||
// note: psi attack works with Petrify!
|
||||
attackMonster(dest, AF_MAGIC, moPlayer);
|
||||
useupOrb(itOrbPsi, 30);
|
||||
createNoise(2);
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void gun_attack(cell *dest) {
|
||||
playSound(dest, "orb-ranged");
|
||||
addMessage(XLAT("You shoot %the1!", dest->monst));
|
||||
killWithMessage(dest, false);
|
||||
attackMonster(dest, AF_GUN, moNone);
|
||||
items[itRevolver] --;
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
createNoise(5);
|
||||
monstersTurn();
|
||||
}
|
||||
|
||||
void stun_attack(cell *dest) {
|
||||
addMessage(XLAT("You stun %the1!", dest->monst));
|
||||
dest->stuntime += 5;
|
||||
void checkStunKill(cell *dest) {
|
||||
if(isBird(dest->monst)) {
|
||||
moveEffect(dest, dest, moDeadBird);
|
||||
if(cellUnstableOrChasm(dest)) dest->wall = waChasm;
|
||||
if(isWatery(dest) || dest->wall == waChasm || isFire(dest))
|
||||
killMonster(dest);
|
||||
doesFall(dest);
|
||||
if(isWatery(dest) || dest->wall == waChasm || isFire(dest)) {
|
||||
addMessage(XLAT("%The1 falls!", dest->monst));
|
||||
fallMonster(dest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* if(!isPermanentFlying(dest->monst) && cellEdgeUnstable(dest)) {
|
||||
addMessage(XLAT("%The1 falls!", dest->monst));
|
||||
fallMonster(dest);
|
||||
} */
|
||||
}
|
||||
|
||||
void stun_attack(cell *dest) {
|
||||
playSound(dest, "orb-ranged");
|
||||
addMessage(XLAT("You stun %the1!", dest->monst));
|
||||
dest->stuntime += 5;
|
||||
checkStunKill(dest);
|
||||
useupOrb(itOrbStunning, 10);
|
||||
createNoise(3);
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void placeIllusion(cell *c) {
|
||||
|
@ -688,38 +854,48 @@ void placeIllusion(cell *c) {
|
|||
useupOrb(itOrbIllusion, 5);
|
||||
addMessage(XLAT("You create an Illusion!"));
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void blowoff(cell *cf, cell *ct) {
|
||||
playSound(ct, "orb-ranged");
|
||||
addMessage(XLAT("You blow %the1 away!", cf->monst));
|
||||
pushMonster(ct, cf);
|
||||
if(cf->item == itBabyTortoise) {
|
||||
if(!ct->item) {
|
||||
ct->item = itBabyTortoise;
|
||||
tortoise::babymap[ct] = tortoise::babymap[cf];
|
||||
}
|
||||
tortoise::babymap.erase(cf);
|
||||
cf->item = itNone;
|
||||
}
|
||||
if(cf->item == itBabyTortoise && !ct->item)
|
||||
moveItem(cf, ct, true);
|
||||
items[itOrbAir]--;
|
||||
createNoise(2);
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
void useOrbOfDragon(cell *c) {
|
||||
makeflame(c, 20, false);
|
||||
playSound(c, "fire");
|
||||
addMessage(XLAT("You throw fire!"));
|
||||
useupOrb(itOrbDragon, 5);
|
||||
createNoise(3);
|
||||
bfs();
|
||||
checkmove();
|
||||
checkmoveO();
|
||||
}
|
||||
|
||||
int monstersnearO(orbAction a, cell *c, cell *nocount, eMonster who, cell *pushto, cell *comefrom) {
|
||||
// printf("[a = %d] ", a);
|
||||
if(shmup::on) return 0;
|
||||
if(a == roCheck && multi::players > 1)
|
||||
return 1;
|
||||
else if(a == roMultiCheck) return 0;
|
||||
else return monstersnear(c, nocount, who, pushto, comefrom);
|
||||
}
|
||||
|
||||
bool isCheck(orbAction a) { return a == roCheck || a == roMultiCheck; }
|
||||
bool isWeakCheck(orbAction a) { return a == roCheck || a == roMultiCheck || a == roMouse; }
|
||||
|
||||
eItem targetRangedOrb(cell *c, orbAction a) {
|
||||
|
||||
if(!haveRangedOrb()) return itNone;
|
||||
if(!haveRangedOrb()) {
|
||||
return itNone;
|
||||
}
|
||||
|
||||
if(rosedist(cwt.c) == 1) {
|
||||
int r = rosemap[cwt.c];
|
||||
|
@ -739,37 +915,38 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
// (-1) distance
|
||||
|
||||
if(c == cwt.c || isNeighbor(cwt.c, c)) {
|
||||
if(a == roKeyboard || a == roMouseForce )
|
||||
if(!isWeakCheck(a))
|
||||
addMessage(XLAT("You cannot target that close!"));
|
||||
return itNone;
|
||||
}
|
||||
if(c->cpdist > 7) {
|
||||
if(a != roCheck)
|
||||
if(!isWeakCheck(a))
|
||||
addMessage(XLAT("You cannot target that far away!"));
|
||||
return itNone;
|
||||
}
|
||||
|
||||
// (0-) strong wind
|
||||
if(items[itStrongWind] && c->cpdist == 2 && cwt.c == whirlwind::jumpFromWhereTo(c, true) && !monstersnear(c, NULL, moPlayer, NULL, cwt.c)) {
|
||||
if(a != roCheck) jumpTo(c, itStrongWind);
|
||||
if(items[itStrongWind] && c->cpdist == 2 && cwt.c == whirlwind::jumpFromWhereTo(c, true) && !monstersnearO(a, c, NULL, moPlayer, NULL, cwt.c)) {
|
||||
if(!isCheck(a)) jumpTo(c, itStrongWind);
|
||||
return itStrongWind;
|
||||
}
|
||||
|
||||
// (0x) control
|
||||
if(getMount() && items[itOrbDomination] && dragon::whichturn != turncount) {
|
||||
if(a != roCheck) {
|
||||
if(haveMount() && items[itOrbDomination] && dragon::whichturn != turncount) {
|
||||
if(!isCheck(a)) {
|
||||
dragon::target = c;
|
||||
dragon::whichturn = turncount;
|
||||
addMessage(XLAT("Commanded %the1!", getMount()));
|
||||
checkmove();
|
||||
addMessage(XLAT("Commanded %the1!", haveMount()));
|
||||
checkmoveO();
|
||||
}
|
||||
return itOrbDomination;
|
||||
}
|
||||
|
||||
// (0) telekinesis
|
||||
if(c->item && !itemHidden(c) && !cwt.c->item && items[itOrbTelekinesis] >= fixpower(c->cpdist * c->cpdist) && !cantGetGrimoire(c, a != roCheck)) {
|
||||
if(a != roCheck) telekinesis(c);
|
||||
return itOrbTelekinesis;
|
||||
if(c->item && !itemHiddenFromSight(c) && !cwt.c->item && items[itOrbSpace] >= fixpower(c->cpdist * c->cpdist) && !cantGetGrimoire(c, !isCheck(a))
|
||||
&& c->item != itBarrow) {
|
||||
if(!isCheck(a)) telekinesis(c);
|
||||
return itOrbSpace;
|
||||
}
|
||||
|
||||
// (0') air blow
|
||||
|
@ -781,20 +958,77 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
nowhereToBlow = true;
|
||||
cell *c2 = c->mov[e % c->type];
|
||||
if(c2 && c2->cpdist > c->cpdist && passable(c2, c, P_BLOW)) {
|
||||
if(a != roCheck) blowoff(c, c2);
|
||||
if(!isCheck(a)) blowoff(c, c2);
|
||||
return itOrbAir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nature
|
||||
if(items[itOrbNature] && numplayers() == 1 && c->monst != moFriendlyIvy) {
|
||||
cell *sides[8];
|
||||
int qsides = 0;
|
||||
forCellCM(cf, c)
|
||||
if(cf->monst == moFriendlyIvy) {
|
||||
|
||||
if(c->monst) {
|
||||
if(!canAttack(c, c->monst, cf, moFriendlyIvy, 0)) continue;
|
||||
if(monstersnear(cwt.c, c, moPlayer, NULL, cwt.c)) continue;
|
||||
}
|
||||
else {
|
||||
if(!passable(c, cf, P_ISPLAYER | P_MONSTER)) continue;
|
||||
if(strictlyAgainstGravity(c, cf, false, MF_IVY)) continue;
|
||||
if(monstersnear(cwt.c, NULL, moPlayer, c, cwt.c)) continue;
|
||||
}
|
||||
sides[qsides++] = cf;
|
||||
}
|
||||
|
||||
if(qsides > 0) {
|
||||
if(!isCheck(a)) growIvyTo(c, sides[hrand(qsides)]);
|
||||
return itOrbNature;
|
||||
}
|
||||
}
|
||||
|
||||
// (0'') jump
|
||||
int jumpstate = 0;
|
||||
cell *jumpthru = NULL;
|
||||
|
||||
|
||||
// orb of vaulting
|
||||
if(!shmup::on && items[itOrbDash] && c->cpdist == 2) {
|
||||
int i = items[itOrbAether];
|
||||
if(i) items[itOrbAether] = i-1;
|
||||
cell *c2 = NULL, *c3 = NULL;
|
||||
for(int i=0; i<cwt.c->type; i++) {
|
||||
cell *cc = cwt.c->mov[i];
|
||||
if(isNeighbor(cc, c)) c3 = c2, c2 = cc;
|
||||
}
|
||||
jumpthru = c2;
|
||||
jumpstate = 10;
|
||||
if(jumpstate == 10 && c2) jumpstate = 11;
|
||||
if(jumpstate == 11 && c2->monst) jumpstate = 12;
|
||||
if(jumpstate == 12 && !c3) jumpstate = 13;
|
||||
if(jumpstate == 13 && passable(c2, cwt.c, P_ISPLAYER | P_JUMP1 | P_MONSTER)) jumpstate = 14;
|
||||
if(jumpstate == 14 && passable(c, c2, P_ISPLAYER | P_JUMP2)) jumpstate = 15;
|
||||
if(jumpstate == 15 && canAttack(cwt.c, moPlayer, c2, c2->monst, 0)) jumpstate = 16;
|
||||
if(jumpstate == 16 && !monstersnearO(a, c, c2, moPlayer, NULL, cwt.c)) jumpstate = 17;
|
||||
items[itOrbAether] = i;
|
||||
|
||||
if(jumpstate == 17) {
|
||||
if(!isCheck(a)) {
|
||||
int k = tkills();
|
||||
eMonster m = c2->monst;
|
||||
attackMonster(c2, AF_ORSTUN | AF_MSG, moPlayer);
|
||||
k = tkills() - k;
|
||||
jumpTo(c, itOrbDash, k, m);
|
||||
}
|
||||
return itOrbDash;
|
||||
}
|
||||
}
|
||||
|
||||
if(items[itOrbFrog] && c->cpdist == 2) {
|
||||
jumpstate = 1;
|
||||
int i = items[itOrbGhost];
|
||||
if(i) items[itOrbGhost] = i-1;
|
||||
int i = items[itOrbAether];
|
||||
if(i) items[itOrbAether] = i-1;
|
||||
for(int i=0; i<cwt.c->type; i++) {
|
||||
cell *c2 = cwt.c->mov[i];
|
||||
if(isNeighbor(c2, c)) {
|
||||
|
@ -808,36 +1042,36 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
}
|
||||
}
|
||||
}
|
||||
items[itOrbGhost] = i;
|
||||
if(jumpstate == 3 && !monstersnear(c, NULL, moPlayer, NULL, c)) {
|
||||
items[itOrbAether] = i;
|
||||
if(jumpstate == 3 && !monstersnearO(a, c, NULL, moPlayer, NULL, cwt.c)) {
|
||||
jumpstate = 4;
|
||||
if(a != roCheck) jumpTo(c, itOrbFrog);
|
||||
if(!isCheck(a)) jumpTo(c, itOrbFrog);
|
||||
return itOrbFrog;
|
||||
}
|
||||
}
|
||||
|
||||
// (1) switch with an illusion
|
||||
if(items[itOrbTeleport] && c->monst == moIllusion && !cwt.c->monst) {
|
||||
if(a != roCheck) teleportTo(c);
|
||||
if(items[itOrbTeleport] && c->monst == moIllusion && !cwt.c->monst && teleportAction() == 1) {
|
||||
if(!isCheck(a)) teleportTo(c);
|
||||
return itOrbTeleport;
|
||||
}
|
||||
|
||||
// (2) place illusion
|
||||
if(!shmup::on && items[itOrbIllusion] && c->monst == moNone && c->item == itNone && passable(c, NULL, P_MIRROR)) {
|
||||
if(a != roCheck) placeIllusion(c);
|
||||
if(!isCheck(a)) placeIllusion(c);
|
||||
return itOrbIllusion;
|
||||
}
|
||||
|
||||
// (3) teleport
|
||||
if(items[itOrbTeleport] && c->monst == moNone && (c->item == itNone || itemHidden(c)) &&
|
||||
passable(c, NULL, P_ISPLAYER | P_TELE) && shmup::verifyTeleport()) {
|
||||
if(a != roCheck) teleportTo(c);
|
||||
passable(c, NULL, P_ISPLAYER | P_TELE) && teleportAction() && shmup::verifyTeleport()) {
|
||||
if(!isCheck(a)) teleportTo(c);
|
||||
return itOrbTeleport;
|
||||
}
|
||||
|
||||
// (4) remove an illusion
|
||||
if(!shmup::on && items[itOrbIllusion] && c->monst == moIllusion) {
|
||||
if(a != roCheck) {
|
||||
if(!isCheck(a)) {
|
||||
addMessage(XLAT("You take the Illusion away."));
|
||||
items[itOrbIllusion] += 3; // 100% effective with the Orb of Energy!
|
||||
c->monst = moNone;
|
||||
|
@ -846,43 +1080,43 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
}
|
||||
|
||||
// (4a) colt
|
||||
if(!shmup::on && items[itRevolver] && c->monst && canAttack(cwt.c, moPlayer, c, c->monst, AF_GUN) && !monstersnear(cwt.c, c, moPlayer, NULL, cwt.c)
|
||||
&& c->pathdist <= GUNRANGE) {
|
||||
if(a != roCheck) gun_attack(c);
|
||||
if(!shmup::on && items[itRevolver] && c->monst && canAttack(cwt.c, moPlayer, c, c->monst, AF_GUN)
|
||||
&& c->pathdist <= GUNRANGE && !monstersnearO(a, cwt.c, c, moPlayer, NULL, cwt.c)) {
|
||||
if(!isCheck(a)) gun_attack(c);
|
||||
return itRevolver;
|
||||
}
|
||||
|
||||
// (5) psi blast (non-shmup variant)
|
||||
if(!shmup::on && items[itOrbPsi] && c->monst && (isDragon(c->monst) || !isWorm(c)) && c->monst != moShadow) {
|
||||
if(a != roCheck) psi_attack(c);
|
||||
if(!shmup::on && items[itOrbPsi] && c->monst && (isDragon(c->monst) || !isWorm(c)) && c->monst != moShadow && c->monst != moKrakenH) {
|
||||
if(!isCheck(a)) psi_attack(c);
|
||||
return itOrbPsi;
|
||||
}
|
||||
|
||||
// (5a) summoning
|
||||
if(items[itOrbSummon] && summonedAt(c)) {
|
||||
if(a != roCheck) summonAt(c);
|
||||
if(!isCheck(a)) summonAt(c);
|
||||
return itOrbSummon;
|
||||
}
|
||||
|
||||
// (5b) matter
|
||||
if(items[itOrbMatter] && tempWallPossibleAt(c)) {
|
||||
if(a != roCheck) tempWallAt(c);
|
||||
if(!isCheck(a)) tempWallAt(c);
|
||||
return itOrbMatter;
|
||||
}
|
||||
|
||||
// (5c) stun
|
||||
if(items[itOrbStunning] && c->monst && !isMultitile(c->monst) && c->stuntime < 3 && !shmup::on) {
|
||||
if(a != roCheck) stun_attack(c);
|
||||
if(!isCheck(a)) stun_attack(c);
|
||||
return itOrbStunning;
|
||||
}
|
||||
|
||||
// (6) place fire (non-shmup variant)
|
||||
if(!shmup::on && items[itOrbDragon] && makeflame(c, 20, true)) {
|
||||
if(a != roCheck) useOrbOfDragon(c);
|
||||
if(!isCheck(a)) useOrbOfDragon(c);
|
||||
return itOrbDragon;
|
||||
}
|
||||
|
||||
if(a == roCheck) return itNone;
|
||||
if(isWeakCheck(a)) return itNone;
|
||||
|
||||
if(nowhereToBlow) {
|
||||
addMessage(XLAT("Nowhere to blow %the1!", c->monst));
|
||||
|
@ -911,7 +1145,11 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
else if(items[itOrbTeleport] && c->monst) {
|
||||
addMessage(XLAT("Cannot teleport on a monster!"));
|
||||
}
|
||||
else if(c->item && items[itOrbTelekinesis]) {
|
||||
else if(items[itOrbSpace] && c->item == itBarrow)
|
||||
addMessage(XLAT("%The1 is protected from this kind of magic!", c->item));
|
||||
else if(c->item && items[itOrbSpace] && !itemHiddenFromSight(c)) {
|
||||
if(cwt.c->item)
|
||||
addMessage(XLAT("Cannot use %the1 here!", itOrbSpace));
|
||||
addMessage(XLAT("Not enough power for telekinesis!"));
|
||||
}
|
||||
else if(items[itOrbIllusion] && c->item)
|
||||
|
@ -920,6 +1158,9 @@ eItem targetRangedOrb(cell *c, orbAction a) {
|
|||
addMessage(XLAT("Cannot cast illusion on a monster!"));
|
||||
else if(items[itOrbIllusion] && !passable(c, NULL, P_MIRROR))
|
||||
addMessage(XLAT("Cannot cast illusion here!"));
|
||||
else if(items[itOrbTeleport] && teleportAction() == 0) {
|
||||
addMessage(XLAT("All players are in the game!"));
|
||||
}
|
||||
else if(items[itOrbTeleport] && !passable(c, NULL, P_TELE | P_ISPLAYER)) {
|
||||
addMessage(XLAT("Cannot teleport here!"));
|
||||
}
|
||||
|
|
11854
polygons.cpp
11854
polygons.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
74
rug.cpp
74
rug.cpp
|
@ -3,7 +3,7 @@
|
|||
|
||||
// implementation of the Hypersian Rug mode
|
||||
|
||||
#ifndef MOBILE
|
||||
#ifndef NORUG
|
||||
|
||||
#define TEXTURESIZE (texturesize)
|
||||
#define HTEXTURESIZE (texturesize/2)
|
||||
|
@ -54,6 +54,7 @@ struct rugpoint {
|
|||
double x1, y1;
|
||||
bool valid;
|
||||
bool inqueue;
|
||||
double dist;
|
||||
hyperpoint h;
|
||||
hyperpoint flat;
|
||||
vector<edge> edges;
|
||||
|
@ -72,13 +73,9 @@ vector<triangle> triangles;
|
|||
// construct the graph
|
||||
//---------------------
|
||||
|
||||
map<cell*, hyperpoint> gmatrix;
|
||||
|
||||
void buildVertexInfo(cell *c, transmatrix V) { if(genrug) gmatrix[c] = V*C0; }
|
||||
|
||||
int hyprand;
|
||||
|
||||
rugpoint *addRugpoint(hyperpoint h) {
|
||||
rugpoint *addRugpoint(hyperpoint h, double dist) {
|
||||
rugpoint *m = new rugpoint;
|
||||
m->h = h;
|
||||
|
||||
|
@ -89,14 +86,15 @@ rugpoint *addRugpoint(hyperpoint h) {
|
|||
hpxyz(h[0], h[1], (h[2]-1) * (rand() % 1000 - rand() % 1000) / 1000);
|
||||
m->valid = false;
|
||||
m->inqueue = false;
|
||||
m->dist = dist;
|
||||
points.push_back(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
rugpoint *findRugpoint(hyperpoint h) {
|
||||
rugpoint *findRugpoint(hyperpoint h, double dist) {
|
||||
for(int i=0; i<size(points); i++)
|
||||
if(intval(points[i]->h, h) < 1e-5) return points[i];
|
||||
return addRugpoint(h);
|
||||
return addRugpoint(h, dist);
|
||||
}
|
||||
|
||||
void addNewEdge(rugpoint *e1, rugpoint *e2) {
|
||||
|
@ -116,9 +114,9 @@ void addTriangle(rugpoint *t1, rugpoint *t2, rugpoint *t3) {
|
|||
}
|
||||
|
||||
void addTriangle1(rugpoint *t1, rugpoint *t2, rugpoint *t3) {
|
||||
rugpoint *t12 = findRugpoint(mid(t1->h, t2->h));
|
||||
rugpoint *t23 = findRugpoint(mid(t2->h, t3->h));
|
||||
rugpoint *t31 = findRugpoint(mid(t3->h, t1->h));
|
||||
rugpoint *t12 = findRugpoint(mid(t1->h, t2->h), (t1->dist+ t2->dist)/2);
|
||||
rugpoint *t23 = findRugpoint(mid(t2->h, t3->h), (t1->dist+ t2->dist)/2);
|
||||
rugpoint *t31 = findRugpoint(mid(t3->h, t1->h), (t1->dist+ t2->dist)/2);
|
||||
addTriangle(t1, t12, t31);
|
||||
addTriangle(t12, t2, t23);
|
||||
addTriangle(t23, t3, t31);
|
||||
|
@ -140,7 +138,7 @@ void buildRug() {
|
|||
|
||||
for(int i=0; i<size(dcal); i++)
|
||||
if(gmatrix.count(dcal[i]))
|
||||
vptr[dcal[i]] = addRugpoint(gmatrix[dcal[i]]);
|
||||
vptr[dcal[i]] = addRugpoint(gmatrix[dcal[i]]*C0, dcal[i]->cpdist);
|
||||
|
||||
for(int i=0; i<size(dcal); i++) {
|
||||
cell *c = dcal[i];
|
||||
|
@ -232,7 +230,9 @@ void preset(rugpoint *m) {
|
|||
// m->h = a->h + (b->h-a->h) * az - ah * ort
|
||||
hyperpoint res = a->flat + (b->flat-a->flat) * az - ah * ort;
|
||||
|
||||
for(int i=0; i<3; i++) h[i] += res[i]; q++;
|
||||
for(int i=0; i<3; i++) h[i] += res[i];
|
||||
|
||||
q++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ void subdivide() {
|
|||
rugpoint *m = points[i];
|
||||
for(int j=0; j<size(m->edges); j++) {
|
||||
rugpoint *m2 = m->edges[j].target;
|
||||
rugpoint *mm = addRugpoint(mid(m->h, m2->h));
|
||||
rugpoint *mm = addRugpoint(mid(m->h, m2->h), (m->dist+m2->dist)/2);
|
||||
using namespace hyperpoint_vec;
|
||||
mm->flat = (m->flat + m2->flat) / 2;
|
||||
mm->valid = true; qvalid++;
|
||||
|
@ -334,6 +334,8 @@ void drawTriangle(triangle& t) {
|
|||
rugpoint& m2 = *t.m[1];
|
||||
rugpoint& m3 = *t.m[2];
|
||||
if(!m1.valid || !m2.valid || !m3.valid) return;
|
||||
if(m1.dist >= sightrange+.51 || m2.dist >= sightrange+.51 || m3.dist >= sightrange+.51)
|
||||
return;
|
||||
dt++;
|
||||
double x1, y1, z1;
|
||||
double x2, y2, z2;
|
||||
|
@ -376,6 +378,7 @@ Uint32 *expanded_data;
|
|||
void initTexture() {
|
||||
|
||||
if(!rendernogl) {
|
||||
#ifndef PANDORA
|
||||
FramebufferName = 0;
|
||||
glGenFramebuffers(1, &FramebufferName);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
|
||||
|
@ -400,6 +403,7 @@ void initTexture() {
|
|||
addMessage("Failed to initialize the framebuffer");
|
||||
rugged = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
texture = SDL_CreateRGBSurface(SDL_SWSURFACE,TEXTURESIZE,TEXTURESIZE,32,0,0,0,0);
|
||||
|
@ -430,6 +434,7 @@ void prepareTexture() {
|
|||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TEXTURESIZE, TEXTURESIZE, 0, GL_BGRA, GL_UNSIGNED_BYTE, expanded_data );
|
||||
}
|
||||
else {
|
||||
#ifndef PANDORA
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
|
||||
glViewport(0,0,TEXTURESIZE,TEXTURESIZE);
|
||||
|
||||
|
@ -438,7 +443,8 @@ void prepareTexture() {
|
|||
drawthemap();
|
||||
if(!renderonce) queueline(C0, mouseh, 0xFF00FF);
|
||||
drawqueue();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
vid = svid;
|
||||
if(!rendernogl) glViewport(0,0,vid.xres,vid.yres);
|
||||
|
@ -451,9 +457,11 @@ void closeTexture() {
|
|||
delete[] expanded_data;
|
||||
}
|
||||
else {
|
||||
#ifndef PANDORA
|
||||
glDeleteTextures(1, &renderedTexture);
|
||||
glDeleteRenderbuffers(1, &depth_stencil_rb);
|
||||
glDeleteFramebuffers(1, &FramebufferName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,6 +497,7 @@ void drawRugScene() {
|
|||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
xview = vid.xres/(vid.radius*scale);
|
||||
yview = vid.yres/(vid.radius*scale);
|
||||
|
@ -563,7 +572,6 @@ void init() {
|
|||
if(renderonce) prepareTexture();
|
||||
if(!rugged) return;
|
||||
|
||||
gmatrix.clear();
|
||||
genrug = true;
|
||||
drawthemap();
|
||||
genrug = false;
|
||||
|
@ -581,7 +589,6 @@ void close() {
|
|||
triangles.clear();
|
||||
for(int i=0; i<size(points); i++) delete points[i];
|
||||
points.clear();
|
||||
gmatrix.clear();
|
||||
pqueue = queue<rugpoint*> ();
|
||||
}
|
||||
|
||||
|
@ -637,16 +644,22 @@ hyperpoint gethyper(ld x, ld y) {
|
|||
}
|
||||
|
||||
void show() {
|
||||
displayStat( 0, XLAT("hypersian rug mode"), "", ' ');
|
||||
displayStat( 2, XLAT("what's this?"), "", 'h');
|
||||
displayStat( 3, XLAT("take me back"), "", 'q');
|
||||
displayStat( 4, XLAT("enable the Hypersian Rug mode"), "", 'u');
|
||||
displayStat( 6, XLAT("render the texture only once"), ONOFF(renderonce), 'o');
|
||||
displayStat( 7, XLAT("render texture without OpenGL"), ONOFF(rendernogl), 'g');
|
||||
displayStat( 8, XLAT("texture size"), its(texturesize)+"x"+its(texturesize), 's');
|
||||
dialog::init(XLAT("hypersian rug mode"), iinf[itPalace].color, 150, 100);
|
||||
|
||||
dialog::addItem(XLAT("what's this?"), 'h');
|
||||
dialog::addItem(XLAT("take me back"), 'q');
|
||||
dialog::addItem(XLAT("enable the Hypersian Rug mode"), 'u');
|
||||
dialog::addBoolItem(XLAT("render the texture only once"), (renderonce), 'o');
|
||||
dialog::addBoolItem(XLAT("render texture without OpenGL"), (rendernogl), 'g');
|
||||
dialog::addSelItem(XLAT("texture size"), its(texturesize)+"x"+its(texturesize), 's');
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
void handleKey(int uni, int sym) {
|
||||
void handleKey(int sym, int uni) {
|
||||
#ifdef PANDORA
|
||||
rendernogl = true;
|
||||
#endif
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(uni == 'h') {
|
||||
lastmode = cmode;
|
||||
|
@ -661,19 +674,24 @@ void handleKey(int uni, int sym) {
|
|||
"Use arrow keys to rotate, Page Up/Down to zoom.";
|
||||
}
|
||||
else if(uni == 'u') {
|
||||
if(sphere) restartGame('E');
|
||||
if(euclid) restartGame('e');
|
||||
rug::init();
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(uni == 'q')
|
||||
cmode = emChangeMode;
|
||||
else if(uni == 'o')
|
||||
renderonce = !renderonce;
|
||||
#ifndef PANDORA
|
||||
else if(uni == 'g')
|
||||
rendernogl = !rendernogl;
|
||||
#endif
|
||||
else if(uni == 's') {
|
||||
texturesize = 2*texturesize;
|
||||
texturesize *= 2;
|
||||
if(texturesize == 8192) texturesize = 128;
|
||||
dialog::scaleLog();
|
||||
}
|
||||
else if(uni || sym == SDLK_F10)
|
||||
cmode = emChangeMode;
|
||||
}
|
||||
|
||||
void select() {
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
bool audio;
|
||||
string musiclicense;
|
||||
string musfname[landtypes];
|
||||
int musicvolume = 60, effvolume = 60;
|
||||
|
||||
eLand getCurrentLandForMusic() {
|
||||
eLand id = cwt.c->land;
|
||||
if(isHaunted(id)) id = laHaunted;
|
||||
if(id == laWarpSea) id = laWarpCoast;
|
||||
return id;
|
||||
}
|
||||
|
||||
void playSeenSound(cell *c) {
|
||||
if(!c->monst) return;
|
||||
bool nearme = c->cpdist <= 7;
|
||||
forCellEx(c2, c) if(c2->cpdist <= 7) nearme = true;
|
||||
if(!nearme) return;
|
||||
if(c->monst == moEagle)
|
||||
playSound(c, "seen-eagle");
|
||||
else if(c->monst == moEarthElemental)
|
||||
playSound(c, "seen-earth");
|
||||
else if(c->monst == moAirElemental)
|
||||
playSound(c, "seen-air");
|
||||
else if(c->monst == moWaterElemental)
|
||||
playSound(c, "seen-water");
|
||||
else if(c->monst == moFireElemental)
|
||||
playSound(c, "fire");
|
||||
else if(c->monst == moDragonHead)
|
||||
playSound(c, "seen-dragon");
|
||||
else if(c->monst == moWorm)
|
||||
playSound(c, "seen-sandworm");
|
||||
else if(c->monst == moSkeleton && c->land != laDungeon)
|
||||
playSound(c, "seen-skeleton");
|
||||
else if(c->monst == moHexSnake)
|
||||
playSound(c, "seen-snake");
|
||||
else if(c->monst == moWolf || c->monst == moRedFox)
|
||||
playSound(c, "seen-woof");
|
||||
else if(isTroll(c->monst))
|
||||
playSound(c, "seen-troll");
|
||||
else if(c->monst == moNecromancer)
|
||||
playSound(c, "seen-necromancer");
|
||||
else if(c->monst == moGhost)
|
||||
playSound(c, "seen-ghost");
|
||||
else if(c->monst == moRoseBeauty)
|
||||
playSound(c, princessgender() ? "seen-rosebeauty" : "seen-gardener");
|
||||
else if(c->monst == moVizier)
|
||||
playSound(c, "seen-vizier");
|
||||
else if(c->monst == moFireFairy)
|
||||
playSound(c, "seen-fairy");
|
||||
else if(c->monst == moCultist)
|
||||
playSound(c, "seen-cultist");
|
||||
else if(c->monst == moPyroCultist)
|
||||
playSound(c, "seen-cultistfire");
|
||||
else if(c->monst == moCultistLeader)
|
||||
playSound(c, "seen-cultistleader");
|
||||
}
|
||||
|
||||
#ifdef SDLAUDIO
|
||||
|
||||
bool loaded[landtypes];
|
||||
Mix_Music* music[landtypes];
|
||||
int musicpos[landtypes];
|
||||
int musstart;
|
||||
int musfadeval = 2000;
|
||||
|
||||
eLand cid = laNone;
|
||||
|
||||
void handlemusic() {
|
||||
DEBB(DF_GRAPH, (debugfile,"handle music\n"));
|
||||
if(audio && musicvolume) {
|
||||
eLand id = getCurrentLandForMusic();
|
||||
#ifdef LOCAL
|
||||
extern bool local_changemusic(eLand& id);
|
||||
if(local_changemusic(id)) return;
|
||||
#endif
|
||||
if(outoffocus) id = eLand(0);
|
||||
if(musfname[id] == "LAST") id = cid;
|
||||
if(!loaded[id]) {
|
||||
loaded[id] = true;
|
||||
// printf("loading (%d)> %s\n", id, musfname[id].c_str());
|
||||
if(musfname[id] != "") {
|
||||
music[id] = Mix_LoadMUS(musfname[id].c_str());
|
||||
if(!music[id]) {
|
||||
printf("Mix_LoadMUS: %s\n", Mix_GetError());
|
||||
}
|
||||
}
|
||||
}
|
||||
if(cid != id && !musfadeval) {
|
||||
musicpos[cid] = SDL_GetTicks() - musstart;
|
||||
musfadeval = musicpos[id] ? 500 : 2000;
|
||||
Mix_FadeOutMusic(musfadeval);
|
||||
// printf("fadeout %d, pos %d\n", musfadeval, musicpos[cid]);
|
||||
}
|
||||
if(music[id] && !Mix_PlayingMusic()) {
|
||||
cid = id;
|
||||
Mix_VolumeMusic(musicvolume);
|
||||
Mix_FadeInMusicPos(music[id], -1, musfadeval, musicpos[id] / 1000.0);
|
||||
// printf("fadein %d, pos %d\n", musfadeval, musicpos[cid]);
|
||||
musstart = SDL_GetTicks() - musicpos[id];
|
||||
musicpos[id] = 0;
|
||||
musfadeval = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void resetmusic() {
|
||||
if(audio && musicvolume) {
|
||||
Mix_FadeOutMusic(3000);
|
||||
cid = laNone;
|
||||
for(int i=0; i<landtypes; i++) musicpos[i] = 0;
|
||||
musfadeval = 2000;
|
||||
}
|
||||
}
|
||||
|
||||
bool loadMusicInfo(string dir) {
|
||||
DEBB(DF_INIT, (debugfile,"load music info\n"));
|
||||
if(dir == "") return false;
|
||||
FILE *f = fopen(dir.c_str(), "rt");
|
||||
if(f) {
|
||||
string dir2;
|
||||
for(int i=0; i<size(dir); i++) if(dir[i] == '/' || dir[i] == '\\')
|
||||
dir2 = dir.substr(0, i+1);
|
||||
char buf[1000];
|
||||
while(fgets(buf, 800, f) > 0) {
|
||||
for(int i=0; buf[i]; i++) if(buf[i] == 10 || buf[i] == 13) buf[i] = 0;
|
||||
if(buf[0] == '[' && buf[3] == ']') {
|
||||
int id = (buf[1] - '0') * 10 + buf[2] - '0';
|
||||
if(id >= 0 && id < landtypes) {
|
||||
if(buf[5] == '*' && buf[6] == '/') musfname[id] = dir2 + (buf+7);
|
||||
else musfname[id] = buf+5;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "warning: bad soundtrack id, use the following format:\n");
|
||||
fprintf(stderr, "[##] */filename\n");
|
||||
fprintf(stderr, "where ## are two digits, and */ is optional and replaced by path to the music\n");
|
||||
fprintf(stderr, "alternatively LAST = reuse the last track instead of having a special one");
|
||||
}
|
||||
// printf("[%2d] %s\n", id, buf);
|
||||
}
|
||||
else if(buf[0] == '#') {
|
||||
}
|
||||
else {
|
||||
musiclicense += buf;
|
||||
musiclicense += "\n";
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool loadMusicInfo() {
|
||||
return
|
||||
loadMusicInfo(musicfile)
|
||||
|| loadMusicInfo("./hyperrogue-music.txt")
|
||||
|| loadMusicInfo("music/hyperrogue-music.txt")
|
||||
// Destination set by ./configure (in the GitHub repository)
|
||||
#ifdef MUSICDESTDIR
|
||||
|| loadMusicInfo(MUSICDESTDIR)
|
||||
#endif
|
||||
#ifdef FHS
|
||||
|| loadMusicInfo("/usr/share/hyperrogue/hyperrogue-music.txt")
|
||||
|| loadMusicInfo(s0 + getenv("HOME") + "/.hyperrogue-music.txt")
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
void initAudio() {
|
||||
audio = loadMusicInfo();
|
||||
|
||||
if(audio) {
|
||||
if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) != 0) {
|
||||
fprintf(stderr, "Unable to initialize audio: %s\n", Mix_GetError());
|
||||
audio = false;
|
||||
}
|
||||
else {
|
||||
audio = true;
|
||||
Mix_AllocateChannels(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map<string, Mix_Chunk*> chunks;
|
||||
|
||||
string wheresounds = "sounds/";
|
||||
|
||||
void playSound(cell *c, const string& fname, int vol) {
|
||||
if(effvolume == 0) return;
|
||||
// printf("Play sound: %s\n", fname.c_str());
|
||||
if(!chunks.count(fname)) {
|
||||
string s = wheresounds+fname+".ogg";
|
||||
chunks[fname] = Mix_LoadWAV(s.c_str());
|
||||
// printf("Loading, as %p\n", chunks[fname]);
|
||||
}
|
||||
Mix_Chunk *chunk = chunks[fname];
|
||||
if(chunk) {
|
||||
Mix_VolumeChunk(chunk, effvolume * vol / 100);
|
||||
Mix_PlayChannel(-1, chunk, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void resetmusic() {}
|
||||
#endif
|
||||
|
425
system.cpp
425
system.cpp
|
@ -8,6 +8,7 @@ bool cblind;
|
|||
bool autocheat;
|
||||
|
||||
int truelotus;
|
||||
int gamecount;
|
||||
|
||||
time_t timerstart, savetime;
|
||||
bool timerstopped;
|
||||
|
@ -25,26 +26,28 @@ void initgame() {
|
|||
firstland = safetyland;
|
||||
}
|
||||
|
||||
if(tactic::on && euclid) euclidland = firstland;
|
||||
if(tactic::on && (euclid || sphere)) euclidland = firstland;
|
||||
|
||||
if(firstland == laNone || firstland == laBarrier)
|
||||
firstland = laCrossroads;
|
||||
|
||||
if(firstland == laCrossroads5 && !tactic::on) firstland = laCrossroads2; // could not fit!
|
||||
if(firstland == laOceanWall) firstland = laOcean;
|
||||
if(firstland == laHauntedWall) firstland = laGraveyard;
|
||||
if(firstland == laMountain && !tactic::on) firstland = laJungle;
|
||||
if(isGravityLand(firstland) && !tactic::on) firstland = laCrossroads;
|
||||
|
||||
cwt.c = origin.c7; cwt.spin = 0;
|
||||
cwt.c->land = euclid ? euclidland : firstland;
|
||||
cwt.c = origin.c7; cwt.spin = 0; cwt.mirrored = false;
|
||||
cwt.c->land = (euclid || sphere) ? euclidland : firstland;
|
||||
|
||||
chaosAchieved = false;
|
||||
|
||||
if(firstland == laElementalWall) cwt.c->land = randomElementalLand();
|
||||
|
||||
if(tactic::on && (isGravityLand(firstland) || firstland == laOcean))
|
||||
if(tactic::on && (isGravityLand(firstland) || firstland == laOcean) && firstland != laMountain)
|
||||
cwt.c->land = purehepta ? laCrossroads : laCrossroads2;
|
||||
createMov(cwt.c, 0);
|
||||
|
||||
|
||||
setdist(cwt.c, BARLEV, NULL);
|
||||
|
||||
if((tactic::on || yendor::on) && isCyclic(firstland)) {
|
||||
|
@ -64,9 +67,9 @@ void initgame() {
|
|||
}
|
||||
|
||||
if(tactic::on && firstland == laCaribbean) {
|
||||
if(hiitemsMax(itRedGem) >= 25) items[itRedGem] = 25;
|
||||
if(hiitemsMax(itFernFlower) >= 25) items[itFernFlower] = 25;
|
||||
if(hiitemsMax(itWine) >= 25) items[itWine] = 25;
|
||||
if(hiitemsMax(itRedGem) >= 25) items[itRedGem] = min(hiitemsMax(itRedGem), 50);
|
||||
if(hiitemsMax(itFernFlower) >= 25) items[itFernFlower] = min(hiitemsMax(itFernFlower), 50);
|
||||
if(hiitemsMax(itWine) >= 25) items[itWine] = min(hiitemsMax(itWine), 50);
|
||||
}
|
||||
|
||||
if(tactic::on && tactic::trailer)
|
||||
|
@ -90,29 +93,69 @@ void initgame() {
|
|||
if(cwt.c->land == laCrossroads2) {
|
||||
cwt.c->landparam = 12;
|
||||
createMov(cwt.c, 0)->landparam = 44;
|
||||
createMov(cwt.c, 0)->land = laCrossroads2;
|
||||
}
|
||||
|
||||
for(int i=0; i<numplayers(); i++) sword::angle[i] = 11;
|
||||
|
||||
if(!safety) multi::players = vid.scfg.players;
|
||||
if(multi::players < 1 || multi::players > MAXPLAYER)
|
||||
multi::players = 1;
|
||||
multi::whereto[0].d = MD_UNDECIDED;
|
||||
multi::cpid = 0;
|
||||
|
||||
if(shmup::on) shmup::init();
|
||||
|
||||
// extern int sightrange; sightrange = 9;
|
||||
// cwt.c->land = laHell; items[itHell] = 10;
|
||||
for(int i=BARLEV; i>=0; i--) {
|
||||
if(tactic::trailer) safety = true;
|
||||
if(tactic::trailer && cwt.c->land != laClearing) safety = true;
|
||||
setdist(cwt.c, i, NULL);
|
||||
if(tactic::trailer) safety = false;
|
||||
verifycells(&origin);
|
||||
|
||||
if(sphere) verifyDodecahedron();
|
||||
else verifycells(&origin);
|
||||
}
|
||||
|
||||
if(quotient && generateAll(firstland)) {
|
||||
for(int i=0; i<size(quotientspace::allcells); i++)
|
||||
setdist(quotientspace::allcells[i], 8, NULL);
|
||||
}
|
||||
|
||||
|
||||
if(multi::players > 1 && !shmup::on) for(int i=0; i<numplayers(); i++) {
|
||||
int idir = (3 * i) % cwt.c->type;
|
||||
multi::player[i].c = cwt.c->mov[idir];
|
||||
// special case -- otherwise they land on a wall
|
||||
if(firstland == laCrossroads2 && i == 1)
|
||||
multi::player[1].c = cwt.c;
|
||||
if(firstland == laCrossroads2 && i == 6)
|
||||
multi::player[6].c = createMov(createMov(cwt.c, 0), 3);
|
||||
setdist(cwt.c->mov[idir], 0, cwt.c);
|
||||
multi::player[i].spin = 0;
|
||||
multi::flipped[i] = true;
|
||||
multi::whereto[i].d = MD_UNDECIDED;
|
||||
}
|
||||
|
||||
if(tactic::on && tactic::trailer)
|
||||
items[treasureType(firstland)] = 15;
|
||||
|
||||
yendor::init(3);
|
||||
makeEmpty(cwt.c);
|
||||
multi::revive_queue.clear();
|
||||
|
||||
if(shmup::on) shmup::init();
|
||||
if(multi::players > 1 && !shmup::on) {
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
makeEmpty(playerpos(i));
|
||||
}
|
||||
else {
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
makeEmpty(cwt.c);
|
||||
}
|
||||
|
||||
if(!safety) {
|
||||
usedSafety = false;
|
||||
timerstart = time(NULL); turncount = 0; rosewave = 0; rosephase = 0;
|
||||
mapeditor::whichPattern = 0;
|
||||
if(!quotient) mapeditor::whichPattern = 0;
|
||||
mapeditor::whichShape = 0;
|
||||
noiseuntil = 0;
|
||||
sagephase = 0; hardcoreAt = 0;
|
||||
|
@ -127,7 +170,8 @@ void initgame() {
|
|||
if(!randomPatternsMode && !tactic::on && !yendor::on) {
|
||||
if(firstland != (princess::challenge ? laPalace : laIce)) cheater++;
|
||||
}
|
||||
if(princess::challenge) {
|
||||
if(tactic::trailer) ;
|
||||
else if(princess::challenge) {
|
||||
kills[moVizier] = 1;
|
||||
princess::forceMouse = true;
|
||||
if(yendor::everwon)
|
||||
|
@ -141,25 +185,55 @@ void initgame() {
|
|||
items[i] = 10;
|
||||
kills[moYeti] = 1000;
|
||||
} */
|
||||
if(ISANDROID && yendor::on && modecode() != 0)
|
||||
addMessage(XLAT("Note: currently scores are saved only in the normal mode on Android"));
|
||||
if(ISANDROID && tactic::on)
|
||||
addMessage(XLAT("Note: you can play, but scores won't be saved on Android"));
|
||||
|
||||
else if(randomPatternsMode)
|
||||
addMessage(XLAT("Welcome to the Random Pattern mode!"));
|
||||
else if(tactic::on)
|
||||
addMessage(XLAT("You are playing %the1 in the Pure Tactics mode.", firstland));
|
||||
else if(yendor::on)
|
||||
addMessage(XLAT("Welcome to the Yendor Challenge %1!", its(yendor::challenge)));
|
||||
else if(shmup::on) ; // welcome message given elsewhere
|
||||
else if(euclid)
|
||||
addMessage(XLAT("Welcome to the Euclidean mode!"));
|
||||
else if(sphere && euclidland == laHalloween)
|
||||
addMessage(XLAT("Welcome to Halloween!"));
|
||||
else if(elliptic)
|
||||
addMessage(XLAT("Good luck in the elliptic plane!"));
|
||||
else if(sphere)
|
||||
addMessage(XLAT("Welcome to Spherogue!"));
|
||||
#ifdef ROGUEVIZ
|
||||
else if(rogueviz::on)
|
||||
addMessage(XLAT("Welcome to RogueViz!"));
|
||||
#endif
|
||||
else {
|
||||
addMessage(XLAT("Welcome to HyperRogue!"));
|
||||
#ifndef MOBILE
|
||||
#ifdef IOS
|
||||
addMessage(XLAT("Press F1 or right-shift-click things for help."));
|
||||
#else
|
||||
addMessage(XLAT("Press F1 or right-click things for help."));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
usedSafety = true;
|
||||
safety = false;
|
||||
}
|
||||
|
||||
haverose = false; hadrose = false; rosemap.clear();
|
||||
havewhat = hadwhat = 0; rosemap.clear();
|
||||
|
||||
elec::lightningfast = 0;
|
||||
|
||||
lastsafety = gold();
|
||||
bfs();
|
||||
}
|
||||
|
||||
#define MAXBOX 250
|
||||
#define POSSCORE 210 // update this when new boxes are added!
|
||||
bool havesave = true;
|
||||
|
||||
#ifndef NOSAVE
|
||||
#define MAXBOX 300
|
||||
#define POSSCORE 258 // update this when new boxes are added!
|
||||
|
||||
struct score {
|
||||
string ver;
|
||||
|
@ -171,6 +245,7 @@ bool saving, loading, loadingHi;
|
|||
|
||||
string boxname[MAXBOX];
|
||||
bool fakebox[MAXBOX];
|
||||
bool monsbox[MAXBOX];
|
||||
|
||||
void applyBox(int& t) {
|
||||
if(saving) savebox[boxid++] = t;
|
||||
|
@ -181,12 +256,14 @@ void applyBox(int& t) {
|
|||
void applyBoxNum(int& i, string name = "") {
|
||||
fakebox[boxid] = (name == "");
|
||||
boxname[boxid] = name;
|
||||
monsbox[boxid] = false;
|
||||
applyBox(i);
|
||||
}
|
||||
|
||||
void applyBoxBool(bool& b, string name = "") {
|
||||
int i = b;
|
||||
applyBoxNum(i, name);
|
||||
monsbox[boxid] = false;
|
||||
b = i;
|
||||
}
|
||||
|
||||
|
@ -207,6 +284,7 @@ int applyBoxLoad(string name = "") {
|
|||
void applyBoxI(eItem it, bool f = false) {
|
||||
boxname[boxid] = iinf[it].name;
|
||||
fakebox[boxid] = f;
|
||||
monsbox[boxid] = false;
|
||||
if(loadingHi) {
|
||||
updateHi(it, savebox[boxid++]);
|
||||
}
|
||||
|
@ -216,6 +294,7 @@ void applyBoxI(eItem it, bool f = false) {
|
|||
void applyBoxM(eMonster m, bool f = false) {
|
||||
fakebox[boxid] = f;
|
||||
boxname[boxid] = minf[m].name;
|
||||
monsbox[boxid] = true;
|
||||
applyBox(kills[m]);
|
||||
}
|
||||
|
||||
|
@ -231,7 +310,7 @@ void applyBoxes() {
|
|||
applyBoxNum(turncount, "turn count");
|
||||
applyBoxNum(cellcount, "cells generated");
|
||||
|
||||
if(!saving) timerstart = time(NULL);
|
||||
if(loading) timerstart = time(NULL);
|
||||
|
||||
for(int i=0; i<itOrbLightning; i++)
|
||||
if(i == 0) items[i] = 0, applyBoxI(itFernFlower);
|
||||
|
@ -240,7 +319,8 @@ void applyBoxes() {
|
|||
for(int i=0; i<43; i++) {
|
||||
if(loading) kills[i] = 0;
|
||||
bool fake =
|
||||
i == moLesserM || i == moNone || i == moWolfMoved || i == moTentacletail;
|
||||
i == moLesserM || i == moNone || i == moWolfMoved || i == moTentacletail ||
|
||||
i == moIvyNext;
|
||||
if(i == moWormtail) applyBoxM(moCrystalSage);
|
||||
else if(i == moWormwait) applyBoxM(moFireFairy);
|
||||
else if(i == moTentacleEscaping) applyBoxM(moMiner);
|
||||
|
@ -252,17 +332,20 @@ void applyBoxes() {
|
|||
}
|
||||
|
||||
if(saving) {
|
||||
applyBoxSave((int) (savetime + timer - timerstart), "time played");
|
||||
int totaltime = savetime;
|
||||
if(!timerstopped) totaltime += timer - timerstart;
|
||||
applyBoxSave((int) totaltime, "time played");
|
||||
}
|
||||
else if(loading) savetime = applyBoxLoad("time played");
|
||||
else boxid++;
|
||||
else boxname[boxid] = "time played", boxid++;
|
||||
|
||||
if(saving) savecount++;
|
||||
applyBoxNum(savecount, "number of saves");
|
||||
if(saving) savecount--;
|
||||
applyBoxNum(cheater, "number of cheats");
|
||||
|
||||
if(saving) applyBoxSave(items[itOrbSafety] ? safetyland : cwt.c->land, "current land");
|
||||
fakebox[boxid] = true;
|
||||
if(saving) applyBoxSave(items[itOrbSafety] ? safetyland : cwt.c->land, "");
|
||||
else if(loading) firstland = safetyland = eLand(applyBoxLoad());
|
||||
else lostin = eLand(savebox[boxid++]);
|
||||
|
||||
|
@ -275,7 +358,7 @@ void applyBoxes() {
|
|||
applyBoxI(itPower);
|
||||
applyBoxI(itOrbFire, true);
|
||||
applyBoxI(itOrbInvis, true);
|
||||
applyBoxI(itOrbGhost, true);
|
||||
applyBoxI(itOrbAether, true);
|
||||
applyBoxI(itOrbPsi, true);
|
||||
applyBoxM(moBug0);
|
||||
applyBoxM(moBug1);
|
||||
|
@ -302,20 +385,21 @@ void applyBoxes() {
|
|||
applyBoxM(moCShark);
|
||||
applyBoxM(moParrot);
|
||||
applyBoxI(itPirate);
|
||||
applyBoxI(itOrbPreserve, true);
|
||||
applyBoxI(itOrbTime, true);
|
||||
|
||||
applyBoxM(moHexSnake);
|
||||
applyBoxM(moRedTroll);
|
||||
applyBoxI(itRedGem);
|
||||
applyBoxI(itOrbTelekinesis, true);
|
||||
applyBoxI(itOrbSpace, true);
|
||||
|
||||
applyBoxBool(euclid, "Euclidean");
|
||||
int geo = geometry;
|
||||
applyBoxNum(geo, ""); geometry = eGeometry(geo);
|
||||
applyBoxBool(hardcore, "hardcore");
|
||||
applyBoxNum(hardcoreAt, "hardcoreAt");
|
||||
applyBoxNum(hardcoreAt, "");
|
||||
applyBoxBool(shmup::on, "shmup");
|
||||
if(saving) applyBoxSave(euclidland, "euclid land");
|
||||
else if(loading) euclidland = eLand(applyBoxLoad("euclid land"));
|
||||
else boxid++;
|
||||
else fakebox[boxid++] = true;
|
||||
|
||||
applyBoxI(itCoast);
|
||||
applyBoxI(itWhirlpool);
|
||||
|
@ -329,8 +413,8 @@ void applyBoxes() {
|
|||
|
||||
applyBoxI(itPalace);
|
||||
applyBoxI(itFjord);
|
||||
applyBoxI(itOrbFrog);
|
||||
applyBoxI(itOrbDiscord);
|
||||
applyBoxI(itOrbFrog, true);
|
||||
applyBoxI(itOrbDiscord, true);
|
||||
applyBoxM(moPalace);
|
||||
applyBoxM(moFatGuard);
|
||||
applyBoxM(moSkeleton);
|
||||
|
@ -340,15 +424,15 @@ void applyBoxes() {
|
|||
applyBoxM(moWaterElemental);
|
||||
|
||||
applyBoxI(itSavedPrincess);
|
||||
applyBoxI(itOrbLove);
|
||||
applyBoxI(itOrbLove, true);
|
||||
applyBoxM(moPrincess);
|
||||
applyBoxM(moPrincessMoved); // live Princess for Safety
|
||||
applyBoxM(moPrincessArmedMoved); // live Princess for Safety
|
||||
applyBoxM(moPrincessMoved, false); // live Princess for Safety
|
||||
applyBoxM(moPrincessArmedMoved, false); // live Princess for Safety
|
||||
applyBoxM(moMouse);
|
||||
applyBoxNum(princess::saveArmedHP, "save armed HP");
|
||||
applyBoxNum(princess::saveHP, "save HP");
|
||||
applyBoxNum(princess::saveArmedHP, "");
|
||||
applyBoxNum(princess::saveHP, "");
|
||||
|
||||
applyBoxI(itEdge);
|
||||
applyBoxI(itIvory);
|
||||
applyBoxI(itElemental);
|
||||
applyBoxI(itZebra);
|
||||
applyBoxI(itFireShard);
|
||||
|
@ -358,11 +442,11 @@ void applyBoxes() {
|
|||
|
||||
applyBoxM(moAirElemental);
|
||||
applyBoxM(moFireElemental);
|
||||
applyBoxM(moEdgeMonkey);
|
||||
applyBoxM(moFamiliar);
|
||||
applyBoxM(moGargoyle);
|
||||
applyBoxM(moOrangeDog);
|
||||
applyBoxI(itOrbSummon);
|
||||
applyBoxI(itOrbMatter);
|
||||
applyBoxI(itOrbSummon, true);
|
||||
applyBoxI(itOrbMatter, true);
|
||||
|
||||
applyBoxM(moForestTroll);
|
||||
applyBoxM(moStormTroll);
|
||||
|
@ -373,11 +457,11 @@ void applyBoxes() {
|
|||
applyBoxI(itMutant);
|
||||
applyBoxI(itFulgurite);
|
||||
applyBoxI(itBounty);
|
||||
applyBoxI(itOrbLuck);
|
||||
applyBoxI(itOrbLuck, true);
|
||||
applyBoxI(itOrbStunning, true);
|
||||
|
||||
applyBoxBool(tactic::on, "tactic ON");
|
||||
applyBoxNum(elec::lightningfast, "lightningfast");
|
||||
applyBoxBool(tactic::on, "");
|
||||
applyBoxNum(elec::lightningfast, "");
|
||||
|
||||
// if(savebox[boxid]) printf("lotus = %d (lost = %d)\n", savebox[boxid], isHaunted(lostin));
|
||||
if(loadingHi && isHaunted(lostin)) boxid++;
|
||||
|
@ -394,7 +478,7 @@ void applyBoxes() {
|
|||
else applyBoxNum(truelotus, "lotus/escape");
|
||||
applyBoxBool(purehepta, "heptagons only");
|
||||
applyBoxI(itRose);
|
||||
applyBoxI(itOrbSkunk, true);
|
||||
applyBoxI(itOrbBeauty, true);
|
||||
applyBoxI(itCoral);
|
||||
applyBoxI(itOrb37, true);
|
||||
applyBoxI(itOrbEnergy, true);
|
||||
|
@ -403,22 +487,69 @@ void applyBoxes() {
|
|||
applyBoxM(moRoseLady);
|
||||
applyBoxM(moRoseBeauty);
|
||||
applyBoxBool(chaosmode, "Chaos mode");
|
||||
applyBoxNum(shmup::players, "shmup players");
|
||||
applyBoxNum(multi::players, "shmup players");
|
||||
if(multi::players < 1 || multi::players > MAXPLAYER)
|
||||
multi::players = 1;
|
||||
applyBoxM(moRatlingAvenger);
|
||||
// printf("applybox %d\n", shmup::players);
|
||||
|
||||
applyBoxI(itApple);
|
||||
applyBoxM(moKestrel);
|
||||
applyBoxM(moLemur);
|
||||
applyBoxM(moSparrowhawk);
|
||||
applyBoxM(moResearcher);
|
||||
applyBoxI(itDragon);
|
||||
applyBoxM(moDragonHead);
|
||||
applyBoxI(itOrbDomination, true);
|
||||
applyBoxI(itBabyTortoise);
|
||||
applyBoxNum(tortoise::seekbits, "tortoise bits");
|
||||
applyBoxNum(tortoise::seekbits, "");
|
||||
applyBoxM(moTortoise);
|
||||
applyBoxI(itOrbShell, true);
|
||||
|
||||
|
||||
applyBoxNum(safetyseed);
|
||||
|
||||
// (+18)
|
||||
for(int i=0; i<6; i++) {
|
||||
applyBoxNum(multi::treasures[i]);
|
||||
applyBoxNum(multi::kills[i]);
|
||||
applyBoxNum(multi::deaths[i]);
|
||||
}
|
||||
// (+8)
|
||||
applyBoxM(moDragonTail);
|
||||
applyBoxI(itKraken);
|
||||
applyBoxM(moKrakenH);
|
||||
applyBoxM(moKrakenT);
|
||||
applyBoxI(itOrbSword, true);
|
||||
applyBoxI(itBarrow);
|
||||
applyBoxM(moDraugr);
|
||||
applyBoxI(itOrbSword2, true);
|
||||
applyBoxI(itTrollEgg);
|
||||
applyBoxI(itOrbStone, true);
|
||||
|
||||
bool sph;
|
||||
sph = false; applyBoxBool(sph, "sphere"); if(sph) geometry = gSphere;
|
||||
sph = false; applyBoxBool(sph, "elliptic"); if(sph) geometry = gElliptic;
|
||||
applyBox(princess::reviveAt);
|
||||
|
||||
applyBoxI(itDodeca);
|
||||
applyBoxI(itAmethyst);
|
||||
applyBoxI(itSlime);
|
||||
applyBoxI(itOrbNature, true);
|
||||
applyBoxI(itOrbDash, true);
|
||||
// itOrbRecall should not be here
|
||||
applyBoxM(moBat);
|
||||
applyBoxM(moReptile);
|
||||
applyBoxM(moFriendlyIvy);
|
||||
|
||||
applyBoxI(itGreenGrass);
|
||||
applyBoxI(itBull);
|
||||
applyBoxI(itOrbHorns, true);
|
||||
applyBoxI(itOrbBull, true);
|
||||
applyBoxM(moSleepBull);
|
||||
applyBoxM(moRagingBull);
|
||||
applyBoxM(moHerdBull);
|
||||
applyBoxM(moButterfly);
|
||||
applyBoxM(moGadfly);
|
||||
|
||||
if(POSSCORE != boxid) printf("ERROR: %d boxes\n", boxid);
|
||||
}
|
||||
|
||||
void saveBox() {
|
||||
|
@ -432,26 +563,22 @@ void loadBox() {
|
|||
|
||||
void loadBoxHigh() {
|
||||
|
||||
int sp = shmup::players;
|
||||
int son = shmup::on;
|
||||
bool euc = euclid;
|
||||
bool cha = chaosmode;
|
||||
bool ph = purehepta;
|
||||
|
||||
euclid = savebox[116];
|
||||
shmup::on = savebox[119];
|
||||
purehepta = savebox[186];
|
||||
chaosmode = savebox[196];
|
||||
shmup::players = savebox[197];
|
||||
dynamicval<int> sp1(multi::players, savebox[197]);
|
||||
dynamicval<eGeometry> sp2(geometry, (eGeometry) savebox[116]);
|
||||
dynamicval<bool> sp3(shmup::on, savebox[119]);
|
||||
dynamicval<bool> sp4(chaosmode, savebox[196]);
|
||||
dynamicval<bool> sp5(purehepta, savebox[186]);
|
||||
if(savebox[238]) geometry = gSphere;
|
||||
if(savebox[239]) geometry = gElliptic;
|
||||
|
||||
if(shmup::on && !shmup::players) ;
|
||||
if(multi::players < 1 || multi::players > MAXPLAYER)
|
||||
multi::players = 1;
|
||||
|
||||
if(shmup::on && multi::players == 1) ;
|
||||
else {
|
||||
// have boxid
|
||||
boxid = 0; loadingHi = true; applyBoxes(); loadingHi = false;
|
||||
}
|
||||
|
||||
purehepta = ph; chaosmode = cha; euclid = euc; shmup::on = son; shmup::players = sp;
|
||||
|
||||
}
|
||||
|
||||
// certify that saves and achievements were received
|
||||
|
@ -473,11 +600,27 @@ namespace anticheat {
|
|||
|
||||
long long saveposition = -1;
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
void remove_emergency_save() {
|
||||
#ifndef WINDOWS
|
||||
if(saveposition >= 0) {
|
||||
/* if(!timerghost)
|
||||
addMessage(XLAT("Emergency truncate to ") + its(saveposition)); */
|
||||
if(truncate(scorefile, saveposition)) {}
|
||||
saveposition = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void saveStats(bool emergency = false) {
|
||||
DEBB(DF_INIT, (debugfile,"saveStats [%s]\n", scorefile));
|
||||
#ifndef ANDROID
|
||||
|
||||
if(autocheat) return;
|
||||
if(randomPatternsMode) return;
|
||||
|
||||
remove_emergency_save();
|
||||
|
||||
FILE *f = fopen(scorefile, "at");
|
||||
|
||||
|
@ -487,16 +630,12 @@ void saveStats(bool emergency = false) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(saveposition >= 0) {
|
||||
// addMessage(XLAT("Emergency seek to ") + its(saveposition));
|
||||
fseek(f, saveposition, SEEK_SET); saveposition = -1;
|
||||
}
|
||||
if(emergency) {
|
||||
saveposition = ftell(f);
|
||||
// addMessage(XLAT("Emergency save at ") + its(saveposition));
|
||||
// if(!timerghost) addMessage(XLAT("Emergency save at ") + its(saveposition));
|
||||
}
|
||||
|
||||
if(showoff) return;
|
||||
if(showoff) { fclose(f); return; }
|
||||
|
||||
time_t timer;
|
||||
timer = time(NULL);
|
||||
|
@ -558,11 +697,13 @@ void saveStats(bool emergency = false) {
|
|||
fprintf(f, "Total wealth: %d\n", gold());
|
||||
fprintf(f, "Total enemies killed: %d\n", tkills());
|
||||
fprintf(f, "cells generated: %d\n", cellcount);
|
||||
if(pureHardcore()) fprintf(f, "Pure hardcore mode\n");
|
||||
if(purehepta) fprintf(f, "Heptagons only mode\n");
|
||||
if(chaosmode) fprintf(f, "Chaos mode\n");
|
||||
if(shmup::on) fprintf(f, "Shoot-em up mode (%d players)\n", shmup::players);
|
||||
if(shmup::on) fprintf(f, "Shoot-em up mode\n");
|
||||
if(multi::players > 1) fprintf(f, "Multi-player (%d players)\n", multi::players);
|
||||
fprintf(f, "Number of cells explored, by distance from the player:\n");
|
||||
for(int i=0; i<10; i++) fprintf(f, " %d", explore[i]); fprintf(f, "\n");
|
||||
{for(int i=0; i<10; i++) fprintf(f, " %d", explore[i]);} fprintf(f, "\n");
|
||||
/*for(int j=0; j<landtypes; j++) {
|
||||
bool haveland = false;
|
||||
for(int i=0; i<10; i++)
|
||||
|
@ -590,15 +731,12 @@ void saveStats(bool emergency = false) {
|
|||
|
||||
#ifndef MOBILE
|
||||
DEBB(DF_INIT, (debugfile, "Game statistics saved to %s\n", scorefile));
|
||||
addMessage(XLAT("Game statistics saved to %1", scorefile));
|
||||
if(!tactic::trailer)
|
||||
addMessage(XLAT("Game statistics saved to %1", scorefile));
|
||||
#endif
|
||||
fclose(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool havesave = true;
|
||||
|
||||
#ifndef ANDROID
|
||||
// load the save
|
||||
void loadsave() {
|
||||
DEBB(DF_INIT, (debugfile,"loadSave\n"));
|
||||
|
@ -606,6 +744,8 @@ void loadsave() {
|
|||
for(int xc=0; xc<MODECODES; xc++)
|
||||
for(int i=0; i<landtypes; i++) for(int j=0; j<MAXTAC; j++)
|
||||
tactic::lsc[xc][i][j] = -1;
|
||||
|
||||
gamecount = 0;
|
||||
|
||||
FILE *f = fopen(scorefile, "rt");
|
||||
havesave = f;
|
||||
|
@ -617,7 +757,9 @@ void loadsave() {
|
|||
char buf[120];
|
||||
if(fgets(buf, 120, f) == NULL) break;
|
||||
if(buf[0] == 'H' && buf[1] == 'y') {
|
||||
if(fscanf(f, "%s", buf) <= 0) break; sc.ver = buf;
|
||||
gamecount++;
|
||||
if(fscanf(f, "%s", buf) <= 0) break;
|
||||
sc.ver = buf;
|
||||
if(sc.ver < "4.4" || sc.ver == "CHEATER!") { ok = false; continue; }
|
||||
ok = true;
|
||||
for(int i=0; i<MAXBOX; i++) {
|
||||
|
@ -661,16 +803,20 @@ void loadsave() {
|
|||
|
||||
if(buf[0] == 'Y' && buf[1] == 'E' && buf[2] == 'N') {
|
||||
char buf1[80], ver[10];
|
||||
int cid, oy, won, tc, t, ts, cert;
|
||||
int cid, oy, won, tc, t, ts, cert=0;
|
||||
sscanf(buf, "%70s%10s%d%d%d%d%d%d%d",
|
||||
buf1, ver, &cid, &oy, &won, &tc, &t, &ts, &cert);
|
||||
|
||||
if(won) for(int xc=0; xc<MODECODES; xc++)
|
||||
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("8.0f") && oy > 1 && cid == 15))
|
||||
if(!(ver < string("9.3b") && oy > 1 && (cid == 27 || cid == 28)))
|
||||
{
|
||||
yendor::bestscore[xc][cid] = max(yendor::bestscore[xc][cid], oy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,14 +847,25 @@ void loadsave() {
|
|||
void restartGame(char switchWhat) {
|
||||
DEBB(DF_INIT, (debugfile,"restartGame\n"));
|
||||
achievement_final(true);
|
||||
#ifndef NOSAVE
|
||||
saveStats();
|
||||
#endif
|
||||
for(int i=0; i<ittypes; i++) items[i] = 0;
|
||||
for(int i=0; i<motypes; i++) kills[i] = 0;
|
||||
lastkills = 0; for(int i=0; i<motypes; i++) kills[i] = 0;
|
||||
for(int i=0; i<10; i++) explore[i] = 0;
|
||||
for(int i=0; i<10; i++) for(int l=0; l<landtypes; l++)
|
||||
exploreland[i][l] = 0;
|
||||
anticheat::tampered = false; achievementsReceived.clear();
|
||||
|
||||
for(int i=0; i<numplayers(); i++)
|
||||
if(multi::playerActive(i))
|
||||
multi::deaths[i]++;
|
||||
|
||||
#ifndef NOSAVE
|
||||
anticheat::tampered = false;
|
||||
#endif
|
||||
achievementsReceived.clear();
|
||||
princess::saved = false;
|
||||
princess::reviveAt = 0;
|
||||
princess::forceVizier = false;
|
||||
princess::forceMouse = false;
|
||||
knighted = 0;
|
||||
|
@ -716,20 +873,22 @@ void restartGame(char switchWhat) {
|
|||
cellcount = 0;
|
||||
clearMemory();
|
||||
if(switchWhat == 'C') {
|
||||
euclid = yendor::on = tactic::on = princess::challenge = false;
|
||||
geometry = gNormal;
|
||||
yendor::on = tactic::on = princess::challenge = false;
|
||||
resetGeometry();
|
||||
chaosmode = !chaosmode;
|
||||
}
|
||||
if(switchWhat == '7') {
|
||||
if(euclid) euclid = false;
|
||||
if(euclid) geometry = gNormal;
|
||||
purehepta = !purehepta;
|
||||
extern void precalc(); extern void resetGL();
|
||||
precalc(); resetGL();
|
||||
resetGeometry();
|
||||
}
|
||||
if(switchWhat == 'e') {
|
||||
extern void precalc(); extern void resetGL();
|
||||
if(chaosmode) chaosmode = false;
|
||||
if(purehepta) { purehepta = false; precalc(); resetGL(); }
|
||||
euclid = !euclid;
|
||||
if(switchWhat == 'g') {
|
||||
if(geometry == targetgeometry) geometry = gNormal;
|
||||
else geometry = targetgeometry;
|
||||
if(chaosmode && geometry != gNormal) chaosmode = false;
|
||||
if(purehepta && euclid) purehepta = false;
|
||||
resetGeometry();
|
||||
}
|
||||
if(switchWhat == 'y') {
|
||||
yendor::on = !yendor::on;
|
||||
|
@ -794,11 +953,12 @@ void clearGameMemory() {
|
|||
DEBB(DF_INIT, (debugfile,"clearGameMemory\n"));
|
||||
pathq.clear();
|
||||
dcal.clear();
|
||||
yendor::yii = 0; yendor::yi.clear();
|
||||
yendor::yii = NOYENDOR; yendor::yi.clear();
|
||||
clearshadow();
|
||||
offscreen.clear();
|
||||
princess::clear();
|
||||
buggycells.clear();
|
||||
mirrors.clear();
|
||||
clearing::bpdata.clear();
|
||||
tortoise::emap.clear();
|
||||
tortoise::babymap.clear();
|
||||
|
@ -809,6 +969,15 @@ void clearGameMemory() {
|
|||
conformal::movehistory.clear();
|
||||
conformal::includeHistory = false;
|
||||
#endif
|
||||
recallCell = NULL;
|
||||
prairie::lasttreasure = NULL;
|
||||
prairie::enter = NULL;
|
||||
prairie::tchoices.clear();
|
||||
prairie::beaststogen.clear();
|
||||
butterflies.clear();
|
||||
#ifdef ROGUEVIZ
|
||||
rogueviz::close();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int orbid = 0;
|
||||
|
@ -835,7 +1004,12 @@ eItem randomTreasure2(int cv) {
|
|||
if(itemclass(i) != IC_TREASURE) continue;
|
||||
int q = 2*items[i];
|
||||
if(a == lt) q -= (2*cv-1);
|
||||
if(a == itEmerald && bearsCamelot(cwt.c->land)) q -= 5;
|
||||
if(a == itEmerald && bearsCamelot(cwt.c->land)) q -= 8;
|
||||
if(a == itElixir && isCrossroads(cwt.c->land)) q -= 7;
|
||||
if(a == itIvory && isCrossroads(cwt.c->land)) q -= 6;
|
||||
if(a == itPalace && isCrossroads(cwt.c->land)) q -= 5;
|
||||
if(a == itIvory && cwt.c->land == laJungle) q -= 5;
|
||||
if(a == itIvory && cwt.c->land == laPalace) q -= 5;
|
||||
if(q < bq) bq = q, cq = 0;
|
||||
if(q == bq) { cq++; if(hrand(cq) == 0) best = i; }
|
||||
}
|
||||
|
@ -844,10 +1018,20 @@ eItem randomTreasure2(int cv) {
|
|||
|
||||
bool isTechnicalLand(eLand l) {
|
||||
return l == laNone || l == laOceanWall || l == laBarrier || l == laCanvas ||
|
||||
l == laHauntedWall || l == laHauntedBorder;
|
||||
l == laHauntedWall || l == laHauntedBorder || l == laCA;
|
||||
}
|
||||
|
||||
eLand cheatdest;
|
||||
|
||||
void cheatMoveTo(eLand l) {
|
||||
cheatdest = l;
|
||||
if(l == laCrossroads5) l = laCrossroads;
|
||||
activateSafety(l);
|
||||
cheatdest = laNone;
|
||||
}
|
||||
|
||||
bool applyCheat(char u, cell *c = NULL) {
|
||||
|
||||
if(u == 'M' && cwt.c->type == 6) {
|
||||
addMessage(XLAT("You summon some Mirages!"));
|
||||
cheater++;
|
||||
|
@ -877,7 +1061,7 @@ bool applyCheat(char u, cell *c = NULL) {
|
|||
}
|
||||
if(u == 'C') {
|
||||
cheater++;
|
||||
activateSafety(laCrossroads);
|
||||
cheatMoveTo(laCrossroads);
|
||||
addMessage(XLAT("Activated the Hyperstone Quest!"));
|
||||
|
||||
for(int t=1; t<ittypes; t++)
|
||||
|
@ -932,11 +1116,7 @@ bool applyCheat(char u, cell *c = NULL) {
|
|||
return true;
|
||||
}
|
||||
if(u == 'R'-64) buildRosemap();
|
||||
if(u == 'D'-64) {
|
||||
mapeditor::drawplayer = !mapeditor::drawplayer;
|
||||
return true;
|
||||
}
|
||||
#ifndef MOBILE
|
||||
#ifndef NOEDIT
|
||||
if(u == 'A') {
|
||||
lastexplore = turncount;
|
||||
cmode = emMapEditor;
|
||||
|
@ -986,7 +1166,7 @@ bool applyCheat(char u, cell *c = NULL) {
|
|||
addMessage(XLAT("You summon an Ivy!"));
|
||||
cheater++;
|
||||
int i = cwt.spin;
|
||||
int j = cwt.c->spn[i];
|
||||
int j = cwt.c->spn(i);
|
||||
cell* c = cwt.c->mov[i]->mov[(j+3)%cwt.c->mov[i]->type];
|
||||
if(passable(c, NULL, 0)) buildIvy(c, 0, 1);
|
||||
return true;
|
||||
|
@ -1037,8 +1217,9 @@ bool applyCheat(char u, cell *c = NULL) {
|
|||
return true;
|
||||
}
|
||||
if(u == 'Z') {
|
||||
cwt.spin++; flipplayer = false;
|
||||
cwt.spin %= cwt.c->type;
|
||||
flipplayer = false;
|
||||
mirror::spin(1);
|
||||
cwspin(cwt, 1);
|
||||
return true;
|
||||
}
|
||||
if(u == 'J') {
|
||||
|
@ -1058,14 +1239,14 @@ bool applyCheat(char u, cell *c = NULL) {
|
|||
}
|
||||
if(u == 'S') {
|
||||
canmove = true;
|
||||
activateSafety(cwt.c->land);
|
||||
cheatMoveTo(cwt.c->land);
|
||||
items[itOrbSafety] += 3;
|
||||
cheater++; addMessage(XLAT("Activated Orb of Safety!"));
|
||||
return true;
|
||||
}
|
||||
if(u == 'U') {
|
||||
canmove = true;
|
||||
activateSafety(firstland);
|
||||
cheatMoveTo(firstland);
|
||||
cheater++; addMessage(XLAT("Teleported to %1!", firstland));
|
||||
return true;
|
||||
}
|
||||
|
@ -1090,15 +1271,39 @@ bool applyCheat(char u, cell *c = NULL) {
|
|||
cwt.c->mov[i]->item = itOrbYendor;
|
||||
return true;
|
||||
}
|
||||
if(u == 'B'-64) {
|
||||
int i = cwt.spin;
|
||||
sword::angle[0]++;
|
||||
cwt.c->mov[i]->item = hrand(2) ? itOrbSword2 : itOrbSword;
|
||||
return true;
|
||||
}
|
||||
if(u == 'X'-64) {
|
||||
items[itEdge] = 12345;
|
||||
items[itOrbNature] += 50;
|
||||
cheater++;
|
||||
return true;
|
||||
}
|
||||
if(u == 'V'-64) {
|
||||
viewdists = !viewdists;
|
||||
return true;
|
||||
}
|
||||
if(u == 'L'-64) {
|
||||
cell *c = mouseover;
|
||||
describeCell(c);
|
||||
printf("Neighbors:"); for(int i=0; i<c->type; i++) printf("%p ", c->mov[i]);
|
||||
printf("Barrier: dir=%d left=%d right=%d\n",
|
||||
c->bardir, c->barleft, c->barright);
|
||||
return true;
|
||||
}
|
||||
if(u == 'C'-64) {
|
||||
cblind = !cblind;
|
||||
return true;
|
||||
}
|
||||
#ifdef LOCAL
|
||||
if(u == 'D'-64) {
|
||||
cheater = 0; autocheat = 0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
// Hyperbolic Rogue
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
|
||||
// basic utility functions
|
||||
|
||||
#ifdef MOBWEB
|
||||
typedef double ld;
|
||||
#define LDF "%lf"
|
||||
#define PLDF "lf"
|
||||
#define ASINH asinh
|
||||
#else
|
||||
typedef long double ld;
|
||||
#define LDF "%Lf"
|
||||
#define PLDF "Lf"
|
||||
#define ASINH asinhl
|
||||
#endif
|
||||
|
||||
template<class T> int size(const T& x) {return int(x.size()); }
|
||||
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 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
|
||||
if(i < 0) return "-" + llts(-i);
|
||||
if(i < 10) return its((int) i);
|
||||
return llts(i/10) + its(i%10);
|
||||
}
|
||||
string itsh(int i) {static char buf[16]; sprintf(buf, "%03X", i); return buf; }
|
||||
|
||||
// debug utilities
|
||||
|
||||
extern FILE *debugfile;
|
||||
extern int debugflags;
|
||||
|
||||
#ifdef ANDROID
|
||||
#define DEBB(r,x)
|
||||
#else
|
||||
#define DEBB(r,x) { if(debugfile && (!(r) || (debugflags & (r)))) { fprintf x; fflush(debugfile); } }
|
||||
#endif
|
||||
|
||||
#define DF_INIT 0 // always display these
|
||||
#define DF_MSG 0 // always display these
|
||||
#define DF_STEAM 1
|
||||
#define DF_GRAPH 2
|
||||
#define DF_TURN 4
|
||||
#define DF_FIELD 8
|
||||
|
||||
#ifdef PROFILING
|
||||
|
||||
#include <sys/time.h>
|
||||
long long getms() {
|
||||
struct timeval tval;
|
||||
gettimeofday(&tval, NULL);
|
||||
return tval.tv_sec * 1000000 + tval.tv_usec;
|
||||
}
|
||||
|
||||
#define FRAMES 64
|
||||
#define CATS 16
|
||||
|
||||
long long proftable[16][FRAMES];
|
||||
int pframeid;
|
||||
|
||||
void profile_frame() {
|
||||
pframeid++; pframeid %= FRAMES;
|
||||
for(int t=0; t<16; t++) proftable[t][pframeid] = 0;
|
||||
}
|
||||
|
||||
void profile_start(int t) { proftable[t][pframeid] -= getms(); }
|
||||
void profile_stop(int t) { proftable[t][pframeid] += getms(); }
|
||||
|
||||
void profile_info() {
|
||||
for(int t=0; t<16; t++) {
|
||||
sort(proftable[t], proftable[t]+FRAMES);
|
||||
if(proftable[t][FRAMES-1] == 0) continue;
|
||||
long long sum = 0;
|
||||
for(int f=0; f<FRAMES; f++) sum += proftable[t][f];
|
||||
printf("Category %d: avg = %Ld, %Ld..%Ld..%Ld..%Ld..%Ld\n",
|
||||
t, sum / FRAMES, proftable[t][0], proftable[t][16], proftable[t][32],
|
||||
proftable[t][48], proftable[t][63]);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define profile_frame()
|
||||
#define profile_start(t)
|
||||
#define profile_stop(t)
|
||||
#define profile_info()
|
||||
#endif
|
||||
|
267
yendor.cpp
267
yendor.cpp
|
@ -5,7 +5,7 @@
|
|||
// Yendor Quest, together with the Yendor Challenge
|
||||
// also, the Pure Tactics Mode
|
||||
|
||||
#define MODECODES 38
|
||||
#define MODECODES 254
|
||||
|
||||
int hiitemsMax(eItem it) {
|
||||
int mx = 0;
|
||||
|
@ -50,7 +50,7 @@ namespace yendor {
|
|||
int challenge; // id of the challenge
|
||||
int lastchallenge;
|
||||
|
||||
#define YENDORLEVELS 27
|
||||
#define YENDORLEVELS 29
|
||||
|
||||
int bestscore[MODECODES][YENDORLEVELS];
|
||||
|
||||
|
@ -69,6 +69,7 @@ namespace yendor {
|
|||
#define YF_START_AL 2048
|
||||
#define YF_START_CR 4096
|
||||
#define YF_CHAOS 8192
|
||||
#define YF_RECALL 16384
|
||||
|
||||
#define YF_START_ANY (YF_START_AL|YF_START_CR)
|
||||
|
||||
|
@ -103,14 +104,26 @@ namespace yendor {
|
|||
{laWildWest, 0},
|
||||
{laWhirlwind, YF_NEAR_TENT},
|
||||
{laHell, YF_CHAOS | YF_DEAD},
|
||||
{laDragon, YF_DEAD}
|
||||
{laDragon, YF_DEAD},
|
||||
{laReptile, 0},
|
||||
{laTortoise, YF_RECALL},
|
||||
};
|
||||
|
||||
int tscorelast;
|
||||
|
||||
void uploadScore() {
|
||||
int tscore = 0;
|
||||
for(int i=1; i<YENDORLEVELS; i++)
|
||||
if(bestscore[0][i]) tscore += 999 + bestscore[0][i];
|
||||
// printf("Yendor score = %d\n", tscore);
|
||||
|
||||
if(tscore > tscorelast) {
|
||||
tscorelast = tscore;
|
||||
if(tscore >= 1000) achievement_gain("YENDC1", 'x');
|
||||
if(tscore >= 5000) achievement_gain("YENDC2", 'x');
|
||||
if(tscore >= 15000) achievement_gain("YENDC3", 'x');
|
||||
}
|
||||
|
||||
achievement_score(LB_YENDOR_CHALLENGE, tscore);
|
||||
}
|
||||
|
||||
|
@ -134,7 +147,8 @@ namespace yendor {
|
|||
|
||||
vector<yendorinfo> yi;
|
||||
|
||||
int yii = 0;
|
||||
#define NOYENDOR 999999
|
||||
int yii = NOYENDOR;
|
||||
|
||||
int hardness() {
|
||||
int thf = 0;
|
||||
|
@ -156,11 +170,10 @@ namespace yendor {
|
|||
return ysUntouched;
|
||||
}
|
||||
|
||||
bool check(cell *yendor, bool checkonly) {
|
||||
bool check(cell *yendor) {
|
||||
int byi = size(yi);
|
||||
for(int i=0; i<size(yi); i++) if(yi[i].path[0] == yendor) byi = i;
|
||||
if(byi < size(yi) && yi[byi].found) return true;
|
||||
if(checkonly) return false;
|
||||
if(byi < size(yi) && yi[byi].found) return false;
|
||||
if(byi == size(yi)) {
|
||||
yendorinfo nyi;
|
||||
nyi.path[0] = yendor;
|
||||
|
@ -241,7 +254,7 @@ namespace yendor {
|
|||
generating = false;
|
||||
|
||||
for(int b=10; b>=5; b--) setdist(key, b, nyi.path[YDIST-2]);
|
||||
|
||||
|
||||
for(int i=-1; i<key->type; i++) {
|
||||
cell *c2 = i >= 0 ? key->mov[i] : key;
|
||||
checkTide(c2);
|
||||
|
@ -257,6 +270,7 @@ namespace yendor {
|
|||
c2->wall = waBoat, c2->monst = moPirate, c2->item = itOrbWater;
|
||||
else c2->wall = waNone;
|
||||
}
|
||||
if(c2->wall == waReptile) c2->wall = waNone;
|
||||
if(c2->wall == waMineMine || c2->wall == waMineUnknown)
|
||||
c2->wall = waMineOpen;
|
||||
if(c2->wall == waTrapdoor && i == -1)
|
||||
|
@ -269,14 +283,20 @@ namespace yendor {
|
|||
if(isGravityLand(c2->land) && key->land == c2->land &&
|
||||
c2->landparam < key->landparam && c2->wall != waTrunk)
|
||||
c2->wall = waPlatform;
|
||||
if(c2->land == laReptile && i >= 0)
|
||||
c2->wall = waChasm;
|
||||
}
|
||||
key->item = itKey;
|
||||
|
||||
yi.push_back(nyi);
|
||||
}
|
||||
yii = byi;
|
||||
addMessage(XLAT("You need to find the right Key to unlock this Orb of Yendor!"));
|
||||
achievement_gain("YENDOR1");
|
||||
if(yii != byi) {
|
||||
yii = byi;
|
||||
achievement_gain("YENDOR1");
|
||||
playSound(yendor, "pickup-yendor");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -314,6 +334,16 @@ namespace yendor {
|
|||
if(clev().flags & YF_DEAD) items[itGreenStone] = 100;
|
||||
if(clev().flags & YF_DEAD5) items[itGreenStone] = 5;
|
||||
}
|
||||
if(clev().flags & YF_RECALL) {
|
||||
int yq = items[itOrbYendor];
|
||||
items[itOrbRecall] = 60 - yq;
|
||||
items[itOrbTime] = 60 - yq;
|
||||
items[itOrbEnergy] = 60 - yq;
|
||||
items[itOrbTeleport] = 60 - yq;
|
||||
items[itOrbSpace] = 60 - yq;
|
||||
items[itOrbDash] = 60 - yq;
|
||||
items[itOrbFrog] = 60 - yq;
|
||||
}
|
||||
nexttostart = laNone;
|
||||
}
|
||||
|
||||
|
@ -321,7 +351,7 @@ namespace yendor {
|
|||
cell *c2 = cwt.c->mov[0];
|
||||
c2->land = firstland;
|
||||
if(firstland == laRlyeh) c2->wall = waNone;
|
||||
yendor::check(c2, false);
|
||||
yendor::check(c2);
|
||||
if(clev().flags & YF_NEAR_IVY)
|
||||
nexttostart = laJungle;
|
||||
if(clev().flags & YF_NEAR_TENT)
|
||||
|
@ -354,6 +384,7 @@ namespace yendor {
|
|||
makeEmpty(c2);
|
||||
c2->item = itOrbYendor;
|
||||
nexttostart = laNone;
|
||||
if(clev().flags & YF_RECALL) recallCell = cwt.c;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,6 +399,7 @@ namespace yendor {
|
|||
if((ylev.flags & YF_NEAR_TENT) && hiitemsMax(itStatue) < 10) return false;
|
||||
if((ylev.flags & YF_CHAOS) && !chaosUnlocked) return false;
|
||||
if((ylev.flags & (YF_DEAD|YF_DEAD5)) && hiitemsMax(itBone) < 10) return false;
|
||||
if((ylev.flags & YF_RECALL) && hiitemsMax(itSlime) < 10) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -380,13 +412,13 @@ namespace yendor {
|
|||
void showMenu() {
|
||||
int s = vid.fsize;
|
||||
vid.fsize = vid.fsize * 4/5;
|
||||
displayStatHelp(-8, XLAT("Yendor Challenge"));
|
||||
dialog::init(XLAT("Yendor Challenge"), iinf[itOrbYendor].color, 150, 100);
|
||||
|
||||
for(int i=1; i<YENDORLEVELS; i++) {
|
||||
string s;
|
||||
yendorlevel& ylev(levels[i]);
|
||||
|
||||
if(levelUnlocked(i)) {
|
||||
if(autocheat || levelUnlocked(i)) {
|
||||
|
||||
s = XLATT1(ylev.l);
|
||||
|
||||
|
@ -399,6 +431,7 @@ namespace yendor {
|
|||
if(ylev.flags & YF_NEAR_RED) { s += "+"; s += XLATT1(laRedRock); }
|
||||
if(ylev.flags & YF_START_AL) { s += "+"; s += XLATT1(laAlchemist); }
|
||||
if(ylev.flags & YF_DEAD) { s += "+"; s += XLATT1(itGreenStone); }
|
||||
if(ylev.flags & YF_RECALL) { s += "+"; s += XLATT1(itOrbRecall); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,14 +445,17 @@ namespace yendor {
|
|||
else if(bestscore[modecode()][i])
|
||||
v = XLAT(" (won at level %1!)", its(bestscore[modecode()][i]));
|
||||
|
||||
displayStat(i-6, s, v, 'a' + i-1);
|
||||
dialog::addSelItem(s, v, 'a' + i-1);
|
||||
}
|
||||
|
||||
displayStat(YENDORLEVELS+1-6, XLAT("Return to the normal game"), "", '0');
|
||||
displayStat(YENDORLEVELS+1-5, XLAT(
|
||||
dialog::addBreak(60);
|
||||
dialog::addItem(XLAT("Return to the normal game"), '0');
|
||||
dialog::addSelItem(XLAT(
|
||||
easy ? "Challenges do not get harder" : "Each challenge gets harder after each victory"),
|
||||
" " + XLAT(easy ? "easy" : "challenge"), '1');
|
||||
|
||||
dialog::display();
|
||||
|
||||
int yc = getcstat - 'a' + 1;
|
||||
if(yc > 0 && yc < YENDORLEVELS) {
|
||||
subscoreboard scorehere;
|
||||
|
@ -463,10 +499,11 @@ namespace yendor {
|
|||
"You get 1000 points for each challenge won, and 1 extra point for "
|
||||
"each extra difficulty level.";
|
||||
|
||||
void handleKey(int uni, int sym) {
|
||||
void handleKey(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni >= 'a' && uni < 'a'+YENDORLEVELS-1) {
|
||||
challenge = uni-'a' + 1;
|
||||
if(levelUnlocked(challenge)) {
|
||||
if(levelUnlocked(challenge) || autocheat) {
|
||||
restartGame(yendor::on ? 0 : 'y');
|
||||
cmode = emNormal;
|
||||
}
|
||||
|
@ -522,6 +559,7 @@ namespace tactic {
|
|||
|
||||
bool tacticUnlocked(int i) {
|
||||
eLand l = land_tac[i].l;
|
||||
if(autocheat) return true;
|
||||
if(l == laWildWest) return true;
|
||||
return hiitemsMax(treasureType(l)) * landMultiplier(l) >= 20;
|
||||
}
|
||||
|
@ -552,11 +590,20 @@ namespace tactic {
|
|||
unrecord(lasttactic);
|
||||
}
|
||||
|
||||
int tscorelast;
|
||||
|
||||
void uploadScoreCode(int code, int lb) {
|
||||
int tscore = 0;
|
||||
for(int i=0; i<landtypes; i++)
|
||||
tscore += recordsum[code][i] * tacmultiplier(eLand(i));
|
||||
// printf("PTM score = %d\n", tscore);
|
||||
|
||||
if(code == 0 && tscore > tscorelast) {
|
||||
tscorelast = tscore;
|
||||
if(tscore >= 1000) achievement_gain("PTM1", 'x');
|
||||
if(tscore >= 5000) achievement_gain("PTM2", 'x');
|
||||
if(tscore >= 15000) achievement_gain("PTM3", 'x');
|
||||
}
|
||||
achievement_score(lb, tscore);
|
||||
}
|
||||
|
||||
|
@ -565,22 +612,41 @@ namespace tactic {
|
|||
uploadScoreCode(2, LB_PURE_TACTICS_SHMUP);
|
||||
uploadScoreCode(4, LB_PURE_TACTICS_COOP);
|
||||
}
|
||||
|
||||
int nl;
|
||||
|
||||
eLand getLandById(int i) {
|
||||
return
|
||||
sphere ? land_sph[i] :
|
||||
euclid ? land_euc[i] :
|
||||
land_tac[i].l;
|
||||
}
|
||||
|
||||
void showMenu() {
|
||||
mouseovers = XLAT("pure tactics mode") + " - " + mouseovers;
|
||||
|
||||
int nl = LAND_TAC;
|
||||
nl = LAND_TAC;
|
||||
|
||||
int vf = min((vid.yres-64) / nl, vid.xres/40);
|
||||
if(euclid) nl = LAND_EUC;
|
||||
if(sphere) nl = LAND_SPH;
|
||||
|
||||
int nlm;
|
||||
int ofs = dialog::handlePage(nl, nlm, nl/2);
|
||||
|
||||
int vf = min((vid.yres-64-vid.fsize) / nlm, vid.xres/40);
|
||||
|
||||
int xr = vid.xres / 64;
|
||||
|
||||
if(on) record(firstland, items[treasureType(firstland)]);
|
||||
|
||||
int xc = modecode();
|
||||
|
||||
getcstat = SDLK_ESCAPE;
|
||||
|
||||
for(int i=0; i<nl; i++) {
|
||||
eLand l = land_tac[i].l;
|
||||
int i1 = i + ofs;
|
||||
eLand l = getLandById(i1);
|
||||
|
||||
int i0 = 56 + i * vf;
|
||||
int col;
|
||||
|
||||
|
@ -588,36 +654,32 @@ namespace tactic {
|
|||
|
||||
if(!ch) continue;
|
||||
|
||||
bool unlocked = tacticUnlocked(i);
|
||||
bool unlocked = tacticUnlocked(i1);
|
||||
|
||||
if(unlocked) col = linf[l].color; else col = 0x202020;
|
||||
|
||||
if(displayfr(xr*1, i0, 1, vf-4, XLAT1(linf[l].name), col, 0) && unlocked) {
|
||||
getcstat = 1000 + i;
|
||||
if(displayfrZ(xr*1, i0, 1, vf-4, XLAT1(linf[l].name), col, 0) && unlocked) {
|
||||
getcstat = 1000 + i1;
|
||||
}
|
||||
|
||||
if(unlocked) {
|
||||
if(unlocked || autocheat) {
|
||||
for(int ii=0; ii<ch; ii++)
|
||||
if(displayfr(xr*(24+2*ii), i0, 1, (vf-4)*4/5, lsc[xc][l][ii] >= 0 ? its(lsc[xc][l][ii]) : "-", col, 16))
|
||||
getcstat = 1000 + i;
|
||||
if(displayfrZ(xr*(24+2*ii), i0, 1, (vf-4)*4/5, lsc[xc][l][ii] >= 0 ? its(lsc[xc][l][ii]) : "-", col, 16))
|
||||
getcstat = 1000 + i1;
|
||||
|
||||
if(displayfr(xr*(24+2*10), i0, 1, (vf-4)*4/5,
|
||||
if(displayfrZ(xr*(24+2*10), i0, 1, (vf-4)*4/5,
|
||||
its(recordsum[xc][l]) + " x" + its(tacmultiplier(l)), col, 0))
|
||||
getcstat = 1000 + i;
|
||||
getcstat = 1000 + i1;
|
||||
}
|
||||
else {
|
||||
int m = landMultiplier(l);
|
||||
displayfr(xr*26, i0, 1, (vf-4)*4/5,
|
||||
displayfrZ(xr*26, i0, 1, (vf-4)*4/5,
|
||||
XLAT("Collect %1x %2 to unlock", its((20+m-1)/m), treasureType(l)),
|
||||
col, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(on || ISIOS) {
|
||||
int i0 = 56 + nl * vf;
|
||||
if(displayfr(xr*24, i0, 1, vf-4, "press 0 to leave this mode", 0xFFD500, 8))
|
||||
getcstat = '0';
|
||||
}
|
||||
dialog::displayPageButtons(3, true);
|
||||
|
||||
uploadScore();
|
||||
if(on) unrecord(firstland);
|
||||
|
@ -635,9 +697,9 @@ namespace tactic {
|
|||
}
|
||||
}
|
||||
|
||||
void handleKey(int uni, int sym) {
|
||||
void handleKey(int sym, int uni) {
|
||||
if(uni >= 1000 && uni < 1000 + LAND_TAC) {
|
||||
firstland = land_tac[uni - 1000].l;
|
||||
firstland = euclidland = getLandById(uni - 1000);
|
||||
restartGame(tactic::on ? 0 : 't');
|
||||
cmode = emNormal;
|
||||
}
|
||||
|
@ -646,7 +708,7 @@ namespace tactic {
|
|||
firstland = laIce;
|
||||
if(tactic::on) restartGame('t');
|
||||
}
|
||||
else if(uni == '2' || sym == SDLK_F1) {
|
||||
else if(sym == SDLK_F1) {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
help =
|
||||
|
@ -673,27 +735,124 @@ namespace tactic {
|
|||
"Good luck, and have fun!";
|
||||
|
||||
}
|
||||
else if(uni) cmode = emNormal;
|
||||
else if(dialog::handlePageButtons(uni)) ;
|
||||
else if(uni || sym == SDLK_F10) cmode = emNormal;
|
||||
}
|
||||
};
|
||||
|
||||
int modecodetable[42][6] = {
|
||||
{ 0, 38, 39, 40, 41, 42}, // softcore hyperbolic
|
||||
{ 7, 43, 44, 45, 46, 47}, // hardcore hyperbolic
|
||||
{ 2, 4, 9, 11, 48, 49}, // shmup hyperbolic
|
||||
{ 13, 50, 51, 52, 53, 54}, // softcore heptagonal hyperbolic
|
||||
{ 16, 55, 56, 57, 58, 59}, // hardcore heptagonal hyperbolic
|
||||
{ 14, 15, 17, 18, 60, 61}, // shmup heptagonal hyperbolic
|
||||
{ 1, 62, 63, 64, 65, 66}, // softcore euclidean
|
||||
{ 8, 67, 68, 69, 70, 71}, // hardcore euclidean
|
||||
{ 3, 5, 10, 12, 72, 73}, // shmup euclidean
|
||||
{110,111,112,113,114,115}, // softcore spherical
|
||||
{116,117,118,119,120,121}, // hardcore spherical
|
||||
{122,123,124,125,126,127}, // shmup spherical
|
||||
{128,129,130,131,132,133}, // softcore heptagonal spherical
|
||||
{134,135,136,137,138,139}, // hardcore heptagonal spherical
|
||||
{140,141,142,143,144,145}, // shmup heptagonal spherical
|
||||
{146,147,148,149,150,151}, // softcore elliptic
|
||||
{152,153,154,155,156,157}, // hardcore elliptic
|
||||
{158,159,160,161,162,163}, // shmup elliptic
|
||||
{164,165,166,167,168,169}, // softcore heptagonal elliptic
|
||||
{170,171,172,173,174,175}, // hardcore heptagonal elliptic
|
||||
{176,177,178,179,180,181}, // shmup heptagonal elliptic
|
||||
{ 19, 74, 75, 76, 77, 78}, // softcore hyperbolic chaosmode
|
||||
{ 26, 79, 80, 81, 82, 83}, // hardcore hyperbolic chaosmode
|
||||
{ 21, 23, 28, 30, 84, 85}, // shmup hyperbolic chaosmode
|
||||
{ 32, 86, 87, 88, 89, 90}, // softcore heptagonal hyperbolic chaosmode
|
||||
{ 35, 91, 92, 93, 94, 95}, // hardcore heptagonal hyperbolic chaosmode
|
||||
{ 33, 34, 36, 37, 96, 97}, // shmup heptagonal hyperbolic chaosmode
|
||||
{ 20, 98, 99,100,101,102}, // softcore euclidean chaosmode
|
||||
{ 27,103,104,105,106,107}, // hardcore euclidean chaosmode
|
||||
{ 22, 24, 29, 31,108,109}, // shmup euclidean chaosmode
|
||||
{182,183,184,185,186,187}, // softcore spherical chaosmode
|
||||
{188,189,190,191,192,193}, // hardcore spherical chaosmode
|
||||
{194,195,196,197,198,199}, // shmup spherical chaosmode
|
||||
{200,201,202,203,204,205}, // softcore heptagonal spherical chaosmode
|
||||
{206,207,208,209,210,211}, // hardcore heptagonal spherical chaosmode
|
||||
{212,213,214,215,216,217}, // shmup heptagonal spherical chaosmode
|
||||
{218,219,220,221,222,223}, // softcore elliptic chaosmode
|
||||
{224,225,226,227,228,229}, // hardcore elliptic chaosmode
|
||||
{230,231,232,233,234,235}, // shmup elliptic chaosmode
|
||||
{236,237,238,239,240,241}, // softcore heptagonal elliptic chaosmode
|
||||
{242,243,244,245,246,247}, // hardcore heptagonal elliptic chaosmode
|
||||
{248,249,250,251,252,253}, // shmup heptagonal elliptic chaosmode
|
||||
};
|
||||
// unused code: 25
|
||||
int newmodecode = 254;
|
||||
|
||||
int modecode() {
|
||||
int xcode = 0;
|
||||
if(euclid) xcode += 1;
|
||||
if(shmup::on) {
|
||||
if(numplayers() == 1) xcode += 2;
|
||||
if(numplayers() == 2) xcode += 4;
|
||||
if(numplayers() == 3) xcode += 9;
|
||||
if(numplayers() == 4) xcode += 11;
|
||||
}
|
||||
if(pureHardcore() && !shmup::on) xcode += 7;
|
||||
#ifndef NOSAVE
|
||||
if(anticheat::tampered || cheater) return 6;
|
||||
if(purehepta) {
|
||||
if(xcode > 6) xcode--;
|
||||
xcode /= 2;
|
||||
xcode += 13;
|
||||
if(quotient) return 6;
|
||||
#endif
|
||||
int xcode = 0;
|
||||
|
||||
if(shmup::on) xcode += 2;
|
||||
else if(pureHardcore()) xcode ++;
|
||||
|
||||
if(euclid) xcode += 6;
|
||||
else if(purehepta) xcode += 3;
|
||||
|
||||
if(sphere) {
|
||||
xcode += 9;
|
||||
if(elliptic) xcode += 6;
|
||||
if(purehepta) xcode += 3;
|
||||
}
|
||||
if(chaosmode && !yendor::on && cmode != emYendor) xcode += 19;
|
||||
return xcode;
|
||||
|
||||
if(chaosmode) xcode += 21;
|
||||
|
||||
int np = numplayers()-1; if(np<0 || np>5) np=5;
|
||||
|
||||
return modecodetable[xcode][np];
|
||||
}
|
||||
|
||||
void buildmodetable() {
|
||||
bool codeused[600];
|
||||
for(int q=0; q<600; q++) codeused[q] = 0;
|
||||
|
||||
codeused[6] = true; // cheater
|
||||
|
||||
printf("int modecodetable[42][6] = {\n");
|
||||
|
||||
for(int b=0; b<42; b++) {
|
||||
extern bool hardcore;
|
||||
hardcore = (b%3 == 1);
|
||||
shmup::on = (b%3 == 2);
|
||||
purehepta = (b/3)%7 == 1 || (b/3)%7 == 4 || (b/3)%7 == 6;
|
||||
geometry = gNormal;
|
||||
if((b/3)%7 == 2) geometry = gEuclid;
|
||||
if((b/3)%7 >= 3) geometry = gSphere;
|
||||
if((b/3)%7 >= 5) geometry = gElliptic;
|
||||
chaosmode = b >= 21;
|
||||
printf(" {");
|
||||
for(int p=0; p<6; p++) {
|
||||
multi::players = p+1;
|
||||
if(p) printf(",");
|
||||
int mc = modecode();
|
||||
if(codeused[mc]) mc = newmodecode++;
|
||||
codeused[mc] = true;
|
||||
printf("%3d", mc);
|
||||
}
|
||||
printf("}, //");
|
||||
if(hardcore) printf(" hardcore");
|
||||
else if(shmup::on) printf(" shmup");
|
||||
else printf(" softcore");
|
||||
if(purehepta) printf(" heptagonal");
|
||||
if(euclid) printf(" euclidean");
|
||||
else if(elliptic) printf(" elliptic");
|
||||
else if(sphere) printf(" spherical");
|
||||
else printf(" hyperbolic");
|
||||
if(chaosmode) printf(" chaosmode");
|
||||
printf("\n");
|
||||
}
|
||||
printf(" }\n");
|
||||
for(int i=0; i<newmodecode; i++) if(!codeused[i]) printf("// unused code: %d\n", i);
|
||||
printf("int newmodecode = %d;\n", newmodecode);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue