hyperrogue/scores.cpp

289 lines
8.6 KiB
C++

#ifndef NOSAVE
vector<score> scores;
int scoresort = 2;
int scoredisplay = 1;
int scorefrom = 0;
int scoremode = 0;
bool scorerev = false;
bool scorecompare(const score& s1, const score &s2) {
return s1.box[scoresort] > s2.box[scoresort];
}
bool fakescore() {
return fakebox[scoredisplay];
}
string displayfor(score* S) {
// printf("S=%p, scoredisplay = %d\n", S, scoredisplay);
if(S == NULL) {
return XLATN(boxname[scoredisplay]);
}
if(scoredisplay == 0) {
char buf[10];
snprintf(buf, 10, "%d:%02d", S->box[0]/60, S->box[0]%60);
return buf;
}
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]);
}
void loadScores() {
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;
{if(fscanf(f, "%s", buf) <= 0) break;} sc.ver = buf;
for(int i=0; i<MAXBOX; i++) {
if(fscanf(f, "%d", &sc.box[i]) <= 0) { boxid = i; break; }
}
for(int i=boxid; i<MAXBOX; i++) sc.box[i] = 0;
if(sc.ver >= "4.4") {
sc.box[0] = sc.box[65];
// the first executable on Steam included a corruption
if(sc.box[65] > 1420000000 && sc.box[65] < 1430000000) {
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(ok && boxid > 20) scores.push_back(sc);
}
}
fclose(f);
addMessage(its(size(scores))+" games have been recorded in "+scorefile);
pushScreen(showScores);
boxid = 0; applyBoxes();
scoresort = 2; reverse(scores.begin(), scores.end());
scoremode = 0;
if(shmup::on) scoremode = 1;
else if(hardcore) scoremode = 2;
scorefrom = 0;
stable_sort(scores.begin(), scores.end(), scorecompare);
#ifdef MOBILE
extern int andmode;
andmode = 2;
#endif
}
vector<pair<string, int> > pickscore_options;
void sortScores() {
if(scorerev) reverse(scores.begin(), scores.end());
else {
scorerev = true;
scoresort = scoredisplay;
stable_sort(scores.begin(), scores.end(), scorecompare);
}
}
void shiftScoreDisplay(int delta) {
scoredisplay = (scoredisplay + POSSCORE + delta) % POSSCORE, scorerev = false;
if(fakescore()) shiftScoreDisplay(delta);
}
void showScores() {
int y = vid.fsize * 7/2;
int bx = vid.fsize;
getcstat = 1;
string modes =
scoremode == 0 ? XLAT(", m - mode: normal") :
scoremode == 1 ? XLAT(", m - mode: shoot'em up") :
scoremode == 2 ? XLAT(", m - mode: hardcore only") :
"?";
if(euclid) modes += XLAT(" (E:%1)", euclidland);
mouseovers = XLAT("t/left/right - change display, up/down - scroll, s - sort by") + modes;
displaystr(bx*4, vid.fsize*2, 0, vid.fsize, "#", forecolor, 16);
displaystr(bx*8, vid.fsize*2, 0, vid.fsize, "$$$", forecolor, 16);
displaystr(bx*12, vid.fsize*2, 0, vid.fsize, XLAT("kills"), forecolor, 16);
displaystr(bx*18, vid.fsize*2, 0, vid.fsize, XLAT("time"), forecolor, 16);
displaystr(bx*22, vid.fsize*2, 0, vid.fsize, XLAT("ver"), forecolor, 16);
displaystr(bx*23, vid.fsize*2, 0, vid.fsize, displayfor(NULL), forecolor, 0);
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]);
bool wrongtype = false;
wrongtype |= (euclid && (!S.box[116] || S.box[120] != euclidland));
wrongtype |= (!euclid && S.box[116]);
wrongtype |= (scoremode == 1 && !S.box[119]);
wrongtype |= (scoremode != 1 && S.box[119]);
wrongtype |= (scoremode == 2 && (!S.box[117] || S.box[118] >= PUREHARDCORE_LEVEL));
if(wrongtype) { id++; continue; }
if(omit) { omit--; rank++; id++; continue; }
char buf[16];
rank++; sprintf(buf, "%d", rank);
displaystr(bx*4, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
sprintf(buf, "%d", S.box[2]);
displaystr(bx*8, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
sprintf(buf, "%d", S.box[3]);
displaystr(bx*12, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
sprintf(buf, "%d:%02d", S.box[0]/60, S.box[0] % 60);
displaystr(bx*18, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
displaystr(bx*22, y, 0, vid.fsize, S.ver, 0xC0C0C0, 16);
displaystr(bx*23, y, 0, vid.fsize, displayfor(&S), 0xC0C0C0, 0);
y += vid.fsize*5/4; id++;
}
#ifdef MOBILE
buttonclicked = false;
displayabutton(-1, +1, XLAT("SORT"), BTON);
displayabutton( 0, +1, XLAT("PICK"), BTON);
displayabutton(+1, +1, XLAT("PLAY"), BTON);
#endif
keyhandler = [] (int sym, int uni) {
#ifndef MOBILE
if(sym == SDLK_LEFT || sym == SDLK_KP4 || sym == 'h' || sym == 'a')
shiftScoreDisplay(-1);
else if(sym == SDLK_RIGHT || sym == SDLK_KP6 || sym == 'l' || sym == 'd')
shiftScoreDisplay(1);
else if(sym == 't') { mapeditor::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') sortScores();
else if(sym == 'm') { scoremode++; scoremode %= 3; }
else if(doexiton(sym, uni)) popScreen();
#else
static int scoredragx, scoredragy;
extern bool clicked, lclicked;
extern int andmode;
if(andmode) {
if(!clicked && !lclicked) {
andmode = 0;
scoredragx = mousex;
scoredragy = mousey;
}
}
else {
if(clicked && !lclicked)
scoredragx = mousex, scoredragy = mousey;
else if(lclicked && !clicked) {
if(mousey > vid.ycenter - 2 * vid.fsize) {
if(mousex < vid.xcenter*2/3) sortScores();
else if(mousex < vid.xcenter*4/3)
cmode = emPickScores;
else andmode = 0, popScreen();
}
}
else if(clicked && lclicked) {
// if(mousex > scoredragx + 80) scoredragx += 80, shiftScoreDisplay(1);
// if(mousex < scoredragx - 80) scoredragx -= 80, shiftScoreDisplay(-1);
while(mousey > scoredragy + vid.fsize) scoredragy += vid.fsize, scorefrom--;
while(mousey < scoredragy - vid.fsize) scoredragy -= vid.fsize, scorefrom++;
}
}
#endif
};
}
bool monsterpage = false;
void showPickScores() {
getcstat = '0';
int d = scoredisplay;
pickscore_options.clear();
scorerev = false;
for(int i=0; i<POSSCORE; i++) {
scoredisplay = i;
if(!fakescore()) {
string s = displayfor(NULL);
if(mapeditor::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 columns = 1 + (q-1) / percolumn;
for(int i=0; i<q; i++) {
int x = 16 + (vid.xres * (i/percolumn)) / columns;
int y = (vid.fsize+3) * (i % percolumn) + vid.fsize*2;
scoredisplay = pickscore_options[i].second;
if(q <= 9)
pickscore_options[i].first = pickscore_options[i].first + " [" + its(i+1) + "]";
if(!fakescore())
displayButton(x, y, pickscore_options[i].first, 1000+i, 0);
}
displayButton(vid.xres/2, vid.yres - vid.fsize*2, "kills", 'm', 8);
scoredisplay = d;
mouseovers = mapeditor::infix;
keyhandler = [] (int sym, int uni) {
extern int andmode;
andmode = 2;
if(uni == 'm') monsterpage = !monsterpage; else
if(uni >= '1' && uni <= '9') uni = uni + 1000 - '1';
else if(uni >= 1000 && uni < 1000 + size(pickscore_options)) {
scoredisplay = pickscore_options[uni - 1000].second;
popScreen();
}
else if(mapeditor::editInfix(uni)) ;
else if(doexiton(sym, uni)) popScreen();
};
}
#endif