// Hyperbolic Rogue -- local score system // Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details #if CAP_SAVE namespace hr { namespace scores { vector scores; score *currentgame; int scorefrom = 0; bool scorerev = false; string csub(const string& str, int q) { int i = 0; for(int j=0; jbox[117] && S->box[118] < PUREHARDCORE_LEVEL; } int modediff(score *S) { int diff = 0; eGeometry g = (eGeometry) S->box[116]; if(S->box[306] != inv::on) diff += 4; if(S->box[238]) g = gSphere; if(S->box[239]) g = gElliptic; if(max(S->box[197], 1) != multi::players) diff += 8; if(S->box[186] != nonbitrunc || S->box[341] != gp::on) diff += 16; if(S->box[341] && gp::on && (S->box[342] != gp::param.first || S->box[343] != gp::param.second)) diff += 16; if(S->box[196] != chaosmode) diff += 32; if(S->box[119] != shmup::on) diff += 64; if(pureHardcore() && !isHardcore(S)) diff += 128; if(g != gNormal && S->box[120] != specialland) diff += 256; if(g != geometry) { diff += 512; } return -diff; } string modedesc(score *S) { eGeometry g = (eGeometry) S->box[116]; if(S->box[238]) g = gSphere; if(S->box[239]) g = gElliptic; string s = ginf[g].shortname; if(g != gNormal) s += " " + csub(XLATT1((eLand) S->box[120]), 3); if(S->box[341]) s += "/GP(" + its(S->box[342])+","+its(S->box[343])+")"; else if(S->box[186]) s += "/7"; if(S->box[196]) s += "/C"; if(S->box[119]) s += "/s"; if(S->box[197] > 1) s += "/P" + its(S->box[197]); if(S->box[306]) s += "/i"; if(isHardcore(S)) s += "/h"; return s; } string displayfor(int scoredisplay, score* S, bool shorten = false) { // printf("S=%p, scoredisplay = %d\n", S, scoredisplay); if(S == NULL) { if(scoredisplay == POSSCORE) return "mode"; string str = XLATN(boxname[scoredisplay]); if(!shorten) return str; if(scoredisplay == 0 || scoredisplay == 65) return XLAT("time"); if(scoredisplay == 2) return "$$$"; if(scoredisplay == 3) return XLAT("kills"); if(scoredisplay == 4) return XLAT("turns"); if(scoredisplay == 5) return XLAT("cells"); if(scoredisplay == 67) return XLAT("cheats"); if(scoredisplay == 66) return XLAT("saves"); if(scoredisplay == 197) return XLAT("players"); return csub(str, 5); } if(scoredisplay == 0 || scoredisplay == 65) { char buf[20]; int t = S->box[0]; if(t >= 3600) snprintf(buf, 20, "%d:%02d:%02d", t/3600, (t/60)%60, t%60); else snprintf(buf, 20, "%d:%02d", t/60, t%60); return buf; } if(scoredisplay == POSSCORE) return modedesc(S); if(scoredisplay == 1) { time_t tim = S->box[1]; char buf[128]; strftime(buf, 128, "%c", localtime(&tim)); return buf; } return its(S->box[scoredisplay]); } vector > pickscore_options; int curcol; vector columns; bool monsterpage = false; void showPickScores() { pickscore_options.clear(); scorerev = false; for(int i=0; i<=POSSCORE; i++) { int scoredisplay = i; if(!fakebox[scoredisplay]) { string s = displayfor(scoredisplay, NULL); if(dialog::hasInfix(s)) if(monsbox[scoredisplay] == monsterpage) pickscore_options.push_back(make_pair(s, i)); } } sort(pickscore_options.begin(), pickscore_options.end()); int q = (int) pickscore_options.size(); int percolumn = vid.yres / (vid.fsize+3) - 4; int qcolumns = 1 + (q-1) / percolumn; for(int i=0; i= '1' && uni <= '9') uni = uni + 1000 - '1'; else if(uni >= 1000 && uni < 1000 + size(pickscore_options)) { int scoredisplay = pickscore_options[uni - 1000].second; for(int i=0; i<=POSSCORE; i++) if(columns[i] == scoredisplay) swap(columns[i], columns[curcol]); popScreen(); } else if(dialog::editInfix(uni)) ; else if(doexiton(sym, uni)) popScreen(); }; } void show() { if(columns.size() == 0) { columns.push_back(POSSCORE); for(int i=0; i vid.xres) break; if(displaystr(bx*at, vid.fsize, 0, vid.fsize, displayfor(c, NULL, true), i == curcol ? 0xFFD500 : forecolor, 0)) getcstat = 1000+i; at += colwidth(c); } if(scorefrom < 0) scorefrom = 0; int id = 0; int omit = scorefrom; int rank = 0; while(y < (ISMOBILE ? vid.yres - 5*vid.fsize : vid.yres - 2 * vid.fsize)) { if(id >= size(scores)) break; score& S(scores[id]); if(omit) { omit--; rank++; id++; continue; } bool cur = S.box[MAXBOX-1]; if(cur) { saveBox(); for(int i=0; i vid.xres) break; at += colwidth(c); if(displaystr(bx*(at-1), y, 0, vid.fsize, displayfor(c, &S), col, 16)) getcstat = 1000+i; } y += vid.fsize*5/4; id++; } int i0 = vid.yres - vid.fsize; int xr = vid.xres / 80; displayButton(xr*10, i0, IFM("s - ") + XLAT("sort"), 's', 8); displayButton(xr*30, i0, IFM("t - ") + XLAT("choose"), 't', 8); displayButton(xr*50, i0, IFM("0 - ") + XLAT("play"), '0', 8); keyhandler = [] (int sym, int uni) { if(sym == SDLK_LEFT || sym == SDLK_KP4 || sym == 'h' || sym == 'a') { scorerev = false; if(curcol > 0) curcol--; } else if(sym == SDLK_RIGHT || sym == SDLK_KP6 || sym == 'l' || sym == 'd') { scorerev = false; if(curcol < POSSCORE) curcol++; } else if(sym >= 1000 && sym <= 1000+POSSCORE) { scorerev = false; curcol = sym - 1000; } else if(sym == 't') { dialog::infix = ""; pushScreen(showPickScores); } else if(sym == SDLK_UP || sym == 'k' || sym == 'w') scorefrom -= 5; else if(sym == SDLK_DOWN || sym == 'j' || sym == 'x') scorefrom += 5; else if(sym == PSEUDOKEY_WHEELUP) scorefrom--; else if(sym == PSEUDOKEY_WHEELDOWN) scorefrom++; else if(sym == 's') { if(scorerev) reverse(scores.begin(), scores.end()); else { scorerev = true; stable_sort(scores.begin(), scores.end(), [] (const score& s1, const score &s2) { return s1.box[columns[curcol]] > s2.box[columns[curcol]]; }); } } else if(doexiton(sym, uni)) popScreen(); static int scoredragy; static bool lclicked; if(mousepressed) { if(!lclicked) { // scoredragx = mousex; scoredragy = mousey; } else { while(mousey > scoredragy + vid.fsize) scoredragy += vid.fsize, scorefrom--; while(mousey < scoredragy - vid.fsize) scoredragy -= vid.fsize, scorefrom++; } lclicked = mousepressed; } }; } void load() { scores.clear(); FILE *f = fopen(scorefile, "rt"); if(!f) { printf("Could not open the score file '%s'!\n", scorefile); addMessage(s0 + "Could not open the score file: " + scorefile); return; } while(!feof(f)) { char buf[120]; if(fgets(buf, 120, f) == NULL) break; if(buf[0] == 'H' && buf[1] == 'y') { score sc; bool ok = true; sc.box[MAXBOX-1] = 0; {if(fscanf(f, "%s", buf) <= 0) break;} sc.ver = buf; for(int i=0; i 1420000000 && sc.box[65] < 1430000000) { sc.box[0] = sc.box[65] - sc.box[1]; sc.box[65] = sc.box[0]; } // do not include saves if(sc.box[65 + 4 + itOrbSafety - itOrbLightning]) ok = false; } else sc.box[0] = sc.box[1] - sc.box[0]; // could not save then if(sc.box[2] == 0) continue; // do not list zero scores sc.box[POSSCORE] = modediff(&sc); if(ok && boxid > 20) scores.push_back(sc); } } saveBox(); score sc; for(int i=0; i tie(s2.box[POSSCORE], s2.box[2]); }); } }} #endif