diff --git a/achievement.cpp b/achievement.cpp index 1fc27434..db1bc281 100644 --- a/achievement.cpp +++ b/achievement.cpp @@ -108,6 +108,7 @@ EX bool wrongMode(char flags) { if(cheater) return true; if(casual) return true; if(flags == rg::global) return false; + if(flags == rg::fail) return true; if(bow::weapon) return true; if(flags != rg::special_geometry && flags != rg::special_geometry_nicewalls) { @@ -131,6 +132,7 @@ EX bool wrongMode(char flags) { if(tour::on) return true; #endif eLandStructure dls = lsNiceWalls; + if(flags == rg::princess && !princess::challenge) return true; if(flags == rg::special_geometry || flags == rg::princess) dls = lsSingle; if(flags == rg::chaos) @@ -160,6 +162,25 @@ EX void achievement_gain_once(const string& s, char flags IS(0)) { achievement_gain(s.c_str(), flags); } +namespace rg { + char check(bool b, char val = special_geometry) { return b ? val : fail; } + }; + +EX char specgeom_zebra() { return rg::check(geometry == gZebraQuotient && !disksize && BITRUNCATED && firstland == laDesert); } +EX char specgeom_lovasz() { return rg::check(geometry == gKleinQuartic && variation == eVariation::untruncated && gp::param == gp::loc(1,1) && !disksize && in_lovasz()); } +EX char specgeom_halloween() { return rg::check((geometry == gSphere || geometry == gElliptic) && BITRUNCATED && !disksize && firstland == laHalloween); } +EX char specgeom_heptagonal() { return rg::check(PURE && geometry == gNormal && !disksize, rg::special_geometry_nicewalls); } +EX char specgeom_euclid_gen() { return rg::check(geometry == gEuclid && !disksize && firstland == laMirrorOld); } +EX char specgeom_crystal1() { return rg::check(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside && !disksize && firstland == laCamelot); } +EX char specgeom_crystal2() { return rg::check(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside && !disksize && firstland == laCamelot); } + +EX vector> all_specgeom_checks = { specgeom_zebra, specgeom_lovasz, specgeom_halloween, specgeom_heptagonal, specgeom_crystal1, specgeom_crystal2, specgeom_euclid_gen }; + +EX char any_specgeom() { + for(auto chk: all_specgeom_checks) if(chk() != rg::fail) return chk(); + return rg::fail; + } + EX void achievement_log(const char* s, char flags) { if(wrongMode(flags)) { @@ -230,11 +251,11 @@ EX void achievement_collection2(eItem it, int q) { if(randomPatternsMode) return; LATE( achievement_collection2(it, q); ) - if(it == itTreat && q == 50 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED && !disksize) - achievement_gain("HALLOWEEN1", rg::special_geometry); + if(it == itTreat && q == 50) + achievement_gain("HALLOWEEN1", specgeom_halloween()); - if(it == itTreat && q == 100 && (geometry == gSphere || geometry == gElliptic) && BITRUNCATED && !disksize) - achievement_gain("HALLOWEEN2", rg::special_geometry); + if(it == itTreat && q == 100) + achievement_gain("HALLOWEEN2", specgeom_halloween()); if(q == 1) { if(it == itDiamond) achievement_gain("DIAMOND1"); @@ -314,13 +335,10 @@ EX void achievement_collection2(eItem it, int q) { // 32 if(it == itHolyGrail) { if(q == 1) achievement_gain("GRAIL2"); - if(PURE && geometry == gNormal && !disksize) - achievement_gain("GRAILH", rg::special_geometry_nicewalls); + achievement_gain("GRAILH", specgeom_heptagonal()); #if CAP_CRYSTAL - if(PURE && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 4 && !crystal::used_compass_inside && !disksize) - achievement_gain("GRAIL4D", rg::special_geometry); - if(BITRUNCATED && cryst && ginf[gCrystal].sides == 8 && ginf[gCrystal].vertex == 3 && !crystal::used_compass_inside && !disksize) - achievement_gain("GRAIL4D2", rg::special_geometry); + achievement_gain("GRAIL4D", specgeom_crystal1()); + achievement_gain("GRAIL4D2", specgeom_crystal2()); #endif if(q == 3) achievement_gain("GRAIL3"); if(q == 8) achievement_gain("GRAIL4"); @@ -604,8 +622,8 @@ EX void achievement_count(const string& s, int current, int prev) { achievement_gain("LIGHTNING2"); if(s == "LIGHTNING" && current-prev >= 10) achievement_gain("LIGHTNING3"); - if(s == "MIRAGE" && current >= 35 && geometry == gEuclid && !disksize) - achievement_gain("MIRAGE", rg::special_geometry); + if(s == "MIRAGE" && current >= 35) + achievement_gain("MIRAGE", specgeom_euclid_gen()); if(s == "ORB" && current >= 10) achievement_gain("ORB3"); if(s == "BUG" && current >= 1000) diff --git a/menus.cpp b/menus.cpp index dcfc8f5b..b9ad5127 100644 --- a/menus.cpp +++ b/menus.cpp @@ -381,6 +381,39 @@ EX void showCreative() { dialog::display(); } +EX void show_achievement_eligibility() { + // #if CAP_ACHIEVE + dialog::addBreak(100); + dialog::addInfo(XLAT("achievement/leaderboard eligiblity:"), 0xFF8000); + if(!wrongMode(0)) + dialog::addInfo(XLAT("eligible for most"), 0x00FF00); + else if(!wrongMode(rg::racing)) + dialog::addInfo(XLAT("eligible for racing"), 0xFFFF00); + else if(!wrongMode(rg::shmup)) + dialog::addInfo(XLAT("eligible for shmup"), 0xFFFF00); + else if(!wrongMode(rg::multi)) + dialog::addInfo(XLAT("eligible for multiplayer"), 0xFFFF00); + else if(!wrongMode(rg::chaos)) + dialog::addInfo(XLAT("eligible for Chaos mode"), 0xFFFF00); + else if(!wrongMode(rg::princess)) + dialog::addInfo(XLAT("eligible for Princess Challenge"), 0xFFFF00); + else if(!wrongMode(specgeom_heptagonal())) + dialog::addInfo(XLAT("eligible for heptagonal"), 0xFFFF00); + else if(!wrongMode(any_specgeom())) /* the player probably knows what they are aiming at */ + dialog::addInfo(XLAT("eligible for special geometry"), 0xFFFF00); + #if CAP_DAILY + else if(daily::on && !daily::historical) + dialog::addInfo(XLAT("eligible for Strange Challenge"), 0xFFFF00); + #endif + else if(cheater) dialog::addInfo(XLAT("disabled in cheat mode"), 0xC00000); + else if(casual) dialog::addInfo(XLAT("disabled in casual mode"), 0xC00000); + else if(ineligible_starting_land) + dialog::addInfo(XLAT("this starting land is not eligible for achievements"), 0xC00000); + else + dialog::addInfo(XLAT("not eligible due to current mode settings"), 0XC00000); + // #endif + } + EX void show_chaos() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(); @@ -420,19 +453,7 @@ EX void show_chaos() { dialog::addSelItem(XLAT("land"), XLAT1(linf[specialland].name), 'l'); dialog::add_action(activate_ge_land_selection); - dialog::addBreak(100); - if(ineligible_starting_land) - dialog::addInfo(XLAT("this starting land is not eligible for achievements")); - else if(land_structure == lsNiceWalls) - dialog::addInfo(XLAT("eligible for most achievements")); - else if(land_structure == lsChaos) - dialog::addInfo(XLAT("eligible for Chaos mode achievements")); - else if(land_structure == lsSingle) - dialog::addInfo(XLAT("eligible for special achievements")); - else - dialog::addInfo(XLAT("not eligible for achievements")); - if(cheater) dialog::addInfo(XLAT("(but the cheat mode is on)")); - if(casual) dialog::addInfo(XLAT("(but the casual mode is on)")); + show_achievement_eligibility(); dialog::addBreak(100); if(ls::horodisk_structure()) @@ -716,8 +737,9 @@ EX void showChangeMode() { dialog::add_action(racing::configure_race); #endif - dialog::addBreak(50); + show_achievement_eligibility(); + dialog::addBreak(50); dialog::addItem(XLAT("highlights & achievements"), 'h'); dialog::add_action_push(mode_higlights); diff --git a/monstermove.cpp b/monstermove.cpp index 102233bc..107b10f7 100644 --- a/monstermove.cpp +++ b/monstermove.cpp @@ -887,8 +887,7 @@ EX void moveWorm(cell *c) { else addMessage(XLAT("The sandworm explodes!")); playSound(NULL, "explosion"); - if(geometry == gZebraQuotient) - achievement_gain_once("ZEBRAWORM", rg::special_geometry); + achievement_gain_once("ZEBRAWORM", specgeom_zebra()); } return; } diff --git a/quit.cpp b/quit.cpp index 90faacb2..b4865427 100644 --- a/quit.cpp +++ b/quit.cpp @@ -369,8 +369,7 @@ EX void showGameMenu() { } dialog::addInfo(XLAT("Dropped floors: %1/%2", its(score), its(all))); if(score == all) dialog::addInfo(XLAT("CONGRATULATIONS!"), iinf[itOrbYendor].color); - if(score == all && geometry == gKleinQuartic && variation == eVariation::untruncated && gp::param == gp::loc(1,1) && !disksize) - achievement_gain_once("LOVASZ", rg::special_geometry); + if(score == all) achievement_gain_once("LOVASZ", specgeom_lovasz()); } else { if(0) diff --git a/system.cpp b/system.cpp index 29f2b7ef..95cec637 100644 --- a/system.cpp +++ b/system.cpp @@ -35,6 +35,8 @@ namespace rg { static constexpr char special_geometry = 'g'; /** \brief wrongmode only -- mark achievements for special geometries/variations */ static constexpr char special_geometry_nicewalls = 'G'; + /** \brief wrongmode only -- specgeom returns 'fail' if the special geometry is not correct */ + static constexpr char fail = 'X'; } #endif