mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-23 13:07:16 +00:00
bringris:: view hiscores, star-based unlock system
This commit is contained in:
parent
d790454fa3
commit
4d8b4b2c8f
@ -80,6 +80,7 @@ struct bgeometry {
|
||||
string name;
|
||||
string cap;
|
||||
flagtype flags;
|
||||
int stars, stars_needed, default_max_piece;
|
||||
reaction_t create;
|
||||
};
|
||||
|
||||
@ -95,8 +96,6 @@ int lti;
|
||||
|
||||
int bgeom = 0;
|
||||
|
||||
int default_max_piece;
|
||||
|
||||
bool rotate_allowed = false;
|
||||
|
||||
bool in_bringris;
|
||||
@ -141,9 +140,11 @@ struct gamedata {
|
||||
ld score;
|
||||
int bricks, completed, cubes, well_size, levelsize, seconds;
|
||||
vector<string> lmap;
|
||||
auto sorter() { static double err = -1; return tie(pro_game ? score : err, completed, bricks, cubes, seconds); }
|
||||
};
|
||||
|
||||
gamedata cur;
|
||||
vector<gamedata> allsaves;
|
||||
|
||||
enum eState {
|
||||
tsPreGame, tsFalling, tsBetween, tsCollect, tsGameover
|
||||
@ -173,7 +174,7 @@ void save();
|
||||
void load();
|
||||
|
||||
vector<bgeometry> bgeoms = {
|
||||
{"Bring surface", "the original Bringris geometry", HYPERBOLIC, [] {
|
||||
{"Bring surface", "the original Bringris geometry", HYPERBOLIC, 0, 0, 4, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 2;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -186,11 +187,10 @@ vector<bgeometry> bgeoms = {
|
||||
set_variation(eVariation::unrectified);
|
||||
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"torus", "Euclidean level geometry", EUCLIDEAN, [] {
|
||||
{"torus", "Euclidean level geometry", EUCLIDEAN, 0, 0, 4, [] {
|
||||
auto& T0 = euc::eu_input.user_axes;
|
||||
T0[0][0] = 5;
|
||||
T0[0][1] = 0;
|
||||
@ -200,19 +200,17 @@ vector<bgeometry> bgeoms = {
|
||||
set_geometry(gEuclidSquare);
|
||||
set_variation(eVariation::pure);
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = true;
|
||||
}},
|
||||
|
||||
{"Cube", "spherical level geometry", SPHERICAL, [] {
|
||||
{"Cube", "spherical level geometry", SPHERICAL, 0, 0, 3, [] {
|
||||
set_geometry(gSmallSphere);
|
||||
set_variation(eVariation::pure);
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 3;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"Klein bottle", "non-orientable manifold", EUCLIDEAN | NONORIENTABLE, [] {
|
||||
{"Klein bottle", "non-orientable manifold", EUCLIDEAN | NONORIENTABLE, 0, 1000, 4, [] {
|
||||
auto& T0 = euc::eu_input.user_axes;
|
||||
T0[0][0] = 5;
|
||||
T0[0][1] = 0;
|
||||
@ -222,11 +220,10 @@ vector<bgeometry> bgeoms = {
|
||||
set_geometry(gEuclidSquare);
|
||||
set_variation(eVariation::pure);
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = true;
|
||||
}},
|
||||
|
||||
{"pentagons", "different tiles on the Bring surface", HYPERBOLIC | HDUAL, [] {
|
||||
{"pentagons", "different tiles on the Bring surface", HYPERBOLIC | HDUAL, 0, 1500, 4, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 2;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -236,11 +233,19 @@ vector<bgeometry> bgeoms = {
|
||||
set_geometry(gFieldQuotient);
|
||||
set_variation(eVariation::pure);
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"double cube", "six squares around a vertex", HYPERBOLIC, [] {
|
||||
{"bounded well", "five squares around a vertex", BOUNDED_WELL, 0, 2000, 4, [] {
|
||||
set_geometry(g45);
|
||||
gp::param = gp::loc(1, 1);
|
||||
set_variation(eVariation::unrectified);
|
||||
set_geometry(gProduct);
|
||||
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"double cube", "six squares around a vertex", HYPERBOLIC, 0, 2500, 3, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 3;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -253,11 +258,10 @@ vector<bgeometry> bgeoms = {
|
||||
set_variation(eVariation::unrectified);
|
||||
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 3;
|
||||
rotate_allowed = true;
|
||||
}},
|
||||
|
||||
{"30/6", "six squares around a vertex", HYPERBOLIC, [] {
|
||||
{"30/6", "six squares around a vertex", HYPERBOLIC, 0, 3000, 4, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 3;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -270,11 +274,10 @@ vector<bgeometry> bgeoms = {
|
||||
set_variation(eVariation::unrectified);
|
||||
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = true;
|
||||
}},
|
||||
|
||||
{"42", "seven squares around a vertex", HYPERBOLIC, [] {
|
||||
{"42", "seven squares around a vertex", HYPERBOLIC, 0, 4000, 4, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 4;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -287,32 +290,20 @@ vector<bgeometry> bgeoms = {
|
||||
set_variation(eVariation::unrectified);
|
||||
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"bounded well", "five squares around a vertex", BOUNDED_WELL, [] {
|
||||
set_geometry(g45);
|
||||
gp::param = gp::loc(1, 1);
|
||||
set_variation(eVariation::unrectified);
|
||||
set_geometry(gProduct);
|
||||
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"mirrored Bring", "hyperbolic and non-orientable", HYPERBOLIC | NONORIENTABLE | ASYMMETRIC_ONLY, [] {
|
||||
{"mirrored Bring", "hyperbolic and non-orientable", HYPERBOLIC | NONORIENTABLE | ASYMMETRIC_ONLY, 0, 5000, 4, [] {
|
||||
set_geometry(gBring);
|
||||
gp::param = gp::loc(1, 1);
|
||||
set_variation(eVariation::unrectified);
|
||||
start_game();
|
||||
subquotient::create_subquotient(2);
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"giant", "like mirrored Bring but much larger", HYPERBOLIC | NONORIENTABLE, [] {
|
||||
{"giant", "like mirrored Bring but much larger", HYPERBOLIC | NONORIENTABLE, 0, 6000, 5, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 2;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -326,12 +317,11 @@ vector<bgeometry> bgeoms = {
|
||||
subquotient::create_subquotient(2);
|
||||
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 5;
|
||||
rotate_allowed = false;
|
||||
cur.well_size = 6;
|
||||
}},
|
||||
|
||||
{"orbifold", "one fifth of the giant", HYPERBOLIC | NONORIENTABLE | ORBIFOLD, [] {
|
||||
{"orbifold", "one fifth of the giant", HYPERBOLIC | NONORIENTABLE | ORBIFOLD, 0, 7000, 4, [] {
|
||||
using namespace fieldpattern;
|
||||
current_extra = 2;
|
||||
auto& gxcur = fgeomextras[current_extra];
|
||||
@ -345,25 +335,22 @@ vector<bgeometry> bgeoms = {
|
||||
subquotient::create_subquotient(10);
|
||||
|
||||
set_geometry(gProduct);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
{"torus: shear", "Nil geometry: are you sure you want this?", SECRET, [] {
|
||||
{"torus: shear", "Nil geometry: are you sure you want this?", SECRET, 0, 10000, 4, [] {
|
||||
nilv::nilperiod = make_array(5, 0, 5);
|
||||
// nilv::set_flags();
|
||||
set_geometry(gNil);
|
||||
default_max_piece = 4;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
|
||||
#if CAP_SOLV
|
||||
{"torus: Arnold's Cat", "Solv geometry: flat shapes are crazy enough", SECRET | FLAT_ONLY, [] {
|
||||
{"torus: Arnold's Cat", "Solv geometry: flat shapes are crazy enough", SECRET | FLAT_ONLY, 0, 12000, 2, [] {
|
||||
asonov::period_xy = 5;
|
||||
asonov::period_z = 0;
|
||||
asonov::set_flags();
|
||||
set_geometry(gArnoldCat);
|
||||
default_max_piece = 2;
|
||||
rotate_allowed = false;
|
||||
}},
|
||||
#endif
|
||||
@ -375,7 +362,7 @@ void enable_bgeom() {
|
||||
stop_game_and_switch_mode(rg::nothing);
|
||||
cur.well_size = 10;
|
||||
bgeoms[bgeom].create();
|
||||
cur.max_piece = default_max_piece;
|
||||
cur.max_piece = bgeoms[bgeom].default_max_piece;
|
||||
start_game();
|
||||
create_game();
|
||||
state = tsPreGame;
|
||||
@ -770,7 +757,7 @@ void new_piece() {
|
||||
if(shape_conflict(at)) {
|
||||
playSound(cwt.at, "die-bomberbird");
|
||||
state = tsGameover;
|
||||
if(cur.pro_game && cur.max_piece == default_max_piece)
|
||||
if(cur.pro_game && cur.max_piece == bgeoms[bgeom].default_max_piece)
|
||||
rv_leaderboard(bgeoms[bgeom].name, cur.score);
|
||||
save();
|
||||
}
|
||||
@ -841,7 +828,7 @@ void find_lines() {
|
||||
cur.score += 100000. * points * (points+1.) / current_move_time_limit();
|
||||
cur.completed += points;
|
||||
playSound(cwt.at, points == 1 ? "pickup-gold" : "orb-mind");
|
||||
if(points == 4 && cur.pro_game && cur.max_piece == 4 && default_max_piece == 4) rv_achievement("BRINGRISFOUR");
|
||||
if(points == 4 && cur.pro_game && cur.max_piece == 4 && bgeoms[bgeom].default_max_piece == 4) rv_achievement("BRINGRISFOUR");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1296,7 +1283,10 @@ void geometry_menu() {
|
||||
clearMessages();
|
||||
dialog::init("Bringris geometries");
|
||||
dialog::addBreak(100);
|
||||
int total_stars = 0;
|
||||
for(int i=0; i<isize(bgeoms); i++) total_stars += bgeoms[i].stars;
|
||||
for(int i=0; i<isize(bgeoms); i++) {
|
||||
if(total_stars >= bgeoms[i].stars_needed) {
|
||||
dialog::addTitle(bgeoms[i].name, i == bgeom ? 0xFF00 : 0xFF0000, 150);
|
||||
dialog::items.back().key = 'a' + i;
|
||||
dialog::add_action([i] {
|
||||
@ -1304,6 +1294,8 @@ void geometry_menu() {
|
||||
});
|
||||
dialog::addInfo(bgeoms[i].cap);
|
||||
dialog::items.back().key = 'a' + i;
|
||||
if(bgeoms[i].stars) dialog::addInfo("stars: " + its(bgeoms[i].stars));
|
||||
else dialog::addBreak(100);
|
||||
dialog::addBreak(50);
|
||||
if(i == bgeom) bgeoms[i].flags &= ~SECRET;
|
||||
if(bgeoms[i].flags & SECRET) {
|
||||
@ -1312,6 +1304,12 @@ void geometry_menu() {
|
||||
dialog::items.pop_back();
|
||||
}
|
||||
}
|
||||
else {
|
||||
dialog::addTitle("locked", 0x404040, 150);
|
||||
dialog::addInfo("stars needed: " + its(bgeoms[i].stars_needed));
|
||||
dialog::addBreak(150);
|
||||
}
|
||||
}
|
||||
dialog::addBreak(100);
|
||||
dialog::addSelItem("max piece", its(cur.max_piece), 'M');
|
||||
dialog::add_action([] {
|
||||
@ -1328,6 +1326,7 @@ void geometry_menu() {
|
||||
dialog::addBreak(100);
|
||||
|
||||
dialog::addBreak(100);
|
||||
dialog::addHelp("1 block removed = 1 star (training) or 5 stars (expert), only best score counts\n\ncurrently " + its(total_stars) + " stars");
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
@ -1418,6 +1417,45 @@ void settings_menu() {
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
bool hi_pro;
|
||||
|
||||
void hiscore_menu() {
|
||||
emptyscreen();
|
||||
dialog::init("High scores");
|
||||
string s = bgeoms[bgeom].name;
|
||||
if(cur.max_piece != bgeoms[bgeom].default_max_piece) s = s + " (block " + its(cur.max_piece) + ")";
|
||||
dialog::addInfo(s);
|
||||
dialog::addItem(hi_pro ? "expert mode" : "training mode", 'm');
|
||||
dialog::add_action([] { hi_pro = !hi_pro; });
|
||||
vector<gamedata*> v;
|
||||
for(auto& ad: allsaves)
|
||||
if(ad.bgeom_name == bgeoms[bgeom].name && ad.max_piece == cur.max_piece && ad.pro_game == hi_pro)
|
||||
v.push_back(&ad);
|
||||
sort(v.begin(), v.end(), [] (gamedata* g1, gamedata* g2) { return g1->sorter() > g2->sorter(); });
|
||||
dialog::start_list(900, 900, '1');
|
||||
for(auto ad: v) {
|
||||
dialog::addSelItem(ad->timerstart, hi_pro ? fts(ad->score) : its(ad->completed), dialog::list_fake_key++);
|
||||
dialog::add_action_push([ad] {
|
||||
emptyscreen();
|
||||
dialog::init();
|
||||
if(hi_pro) dialog::addSelItem("score", fts(ad->score), 's');
|
||||
dialog::addSelItem("levels", fts(ad->completed), 'l');
|
||||
dialog::addSelItem("bricks", fts(ad->bricks), 'b');
|
||||
dialog::addSelItem("cubes", fts(ad->cubes), 'c');
|
||||
dialog::addItem("explore", 'e');
|
||||
dialog::add_action([] {
|
||||
popScreen();
|
||||
popScreen();
|
||||
});
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
});
|
||||
}
|
||||
dialog::end_list();
|
||||
dialog::addBack();
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
void adjust_animation(ld part) {
|
||||
if(solnil) {
|
||||
hyperpoint sh = pView * C0;
|
||||
@ -1641,19 +1679,20 @@ void run() {
|
||||
else if(state == tsGameover) {
|
||||
displayButtonS(xx, vid.fsize * 2, "game over", 0xFFFFFFFF, 8, vid.fsize);
|
||||
}
|
||||
if(displayButtonS(xx, vid.fsize * 4, "NEW GAME", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'n';
|
||||
if(displayButtonS(xx, vid.fsize * 4, "TRAINING", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 't';
|
||||
if(displayButtonS(xx, vid.fsize * 6, "EXPERT GAME", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'x';
|
||||
if(displayButtonS(xx, vid.fsize * 8, "SETTINGS", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 's';
|
||||
if(state != tsPreGame)
|
||||
if(displayButtonS(xx, vid.fsize * 10, "EXPLORE", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'e';
|
||||
if(displayButtonS(xx, vid.fsize * 12, "HI SCORES", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'h';
|
||||
if(!ISWEB) {
|
||||
if(displayButtonS(xx, vid.fsize * 12, "QUIT", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'q';
|
||||
if(displayButtonS(xx, vid.fsize * 14, "QUIT", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'q';
|
||||
}
|
||||
else if(state == tsGameover)
|
||||
if(displayButtonS(xx, vid.fsize * 12, "TWEET", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 't';
|
||||
/* else if(state == tsGameover)
|
||||
if(displayButtonS(xx, vid.fsize * 14, "TWEET", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'T'; */
|
||||
|
||||
if(vrhr::active())
|
||||
if(displayButtonS(xx, vid.fsize * 14, "RESET VR", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'V';
|
||||
if(displayButtonS(xx, vid.fsize * 16, "RESET VR", 0xFFFFFFFF, 8, vid.fsize)) getcstat = 'V';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1741,7 +1780,7 @@ void run() {
|
||||
if(!paused) move_at = move_at - ticks;
|
||||
explore = false;
|
||||
}
|
||||
if(sym == 't' && state == tsGameover) {
|
||||
if(sym == 'T' && state == tsGameover) {
|
||||
const vector<const char*> emoji =
|
||||
{"😀","😎","👽","🤖","😺","🎩","🎓","👑","💍","🐯","🦁","🐮","🐷","🐽","🐸","🐙","🐵","🐦","🐧","🐔","🐒","🙉","🙈","🐣","🐥","🐺","🐗","🐴","🦄","🐝","🐛","🐢","🦀","🦂","🕷","🐜","🐞","🐌","🐠","🐟","🐡","🐬","🐋","🐊","🐆","🐘","🐫","🐪","🐄","🐂","🐃","🐏","🐑","🐀","🐁","🐓","🦃","🐉","🐾","🐿","🐇","🐈","🐩","🐕","🐲","🌵","🍁","🌻","🌎","⭐️","⚡️","🔥","❄️","☔️","☂️","💧","🍏","🍎","🍐","🍋","🍌","🍉","🍇","🌶","🍅","🍍","🍑","🍈","🍓","🌽","🍠","🍯","🍞","🍗","🧀","🍖","🍤","🌯","🌮","🍝","🍕","🌭","🍟","🍔","⚽️","🎱","🏆","🎪","🎲","🎳","🚗","🚕","🚙","🏎","⛺️","⛩","🕹","💾","☎️","⏱","🔦","💡","💰","💎","🔨","💣","🔑","❤️","🔔"};
|
||||
|
||||
@ -1779,7 +1818,7 @@ void run() {
|
||||
if(sym == 'V') {
|
||||
reset_vr_ref();
|
||||
}
|
||||
if(in_menu && sym == 'n') {
|
||||
if(in_menu && sym == 't') {
|
||||
start_new_game();
|
||||
paused = false;
|
||||
explore = false;
|
||||
@ -1789,6 +1828,9 @@ void run() {
|
||||
if(in_menu && sym == 's') {
|
||||
pushScreen(settings_menu);
|
||||
}
|
||||
if(in_menu && sym == 'h') {
|
||||
pushScreen(hiscore_menu);
|
||||
}
|
||||
if(in_menu && sym == 'x') {
|
||||
start_new_game();
|
||||
paused = false;
|
||||
@ -2034,6 +2076,7 @@ void init_all() {
|
||||
showstartmenu = false;
|
||||
pushScreen(run);
|
||||
in_bringris = true;
|
||||
load();
|
||||
}
|
||||
|
||||
int args() {
|
||||
@ -2148,8 +2191,6 @@ auto hook1=
|
||||
});
|
||||
#endif
|
||||
|
||||
vector<gamedata> allsaves;
|
||||
|
||||
void fill_gamedata() {
|
||||
cur.bgeom_name = bgeoms[bgeom].name;
|
||||
time_t timer;
|
||||
@ -2185,9 +2226,30 @@ void save(const gamedata& sd) {
|
||||
void save() {
|
||||
fill_gamedata();
|
||||
save(cur);
|
||||
allsaves.push_back(cur);
|
||||
}
|
||||
|
||||
void load() {
|
||||
allsaves.clear();
|
||||
fhstream f("bringris.save", "rt");
|
||||
if(!f.f) return;
|
||||
string s;
|
||||
while(!feof(f.f)) {
|
||||
s = scanline_noblank(f);
|
||||
if(s == "Bringris 2.0") {
|
||||
gamedata gd;
|
||||
gd.bgeom_name = scanline_noblank(f);
|
||||
gd.timerstart = scanline_noblank(f);
|
||||
gd.timerend = scanline_noblank(f);
|
||||
sscanf(scanline_noblank(f).c_str(), "%d%lf%d%d%d%d%d%d",
|
||||
&gd.max_piece, &gd.score, &gd.bricks, &gd.completed, &gd.cubes, &gd.well_size, &gd.levelsize, &gd.seconds);
|
||||
gd.pro_game = gd.score >= 0;
|
||||
for(int i=0; i<=gd.well_size; i++) gd.lmap.push_back(scanline_noblank(f));
|
||||
allsaves.push_back(gd);
|
||||
for(auto& g: bgeoms) if(g.name == gd.bgeom_name && g.default_max_piece == gd.max_piece)
|
||||
g.stars = max(g.stars, (gd.pro_game ? 5 : 1) * gd.completed * gd.levelsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user