/* highscore.c -- high score routine for Yet Another Mine Sweeper * * Copyright (C) 1992, 1993, 1994 by Hirofumi Yamamoto * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the author not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The author makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * Programmed by hirofumi@info.kawasaki-steel.co.jp for original version. * */ #include #include #ifdef _TIME_H #include #endif #include #include "struct.h" #include "highscore.h" static char rcs_id[] = "$Id: highscore.c,v 1.6 1994/11/03 00:17:08 hirofumi Rel hirofumi $"; #if HIGH_SCORE #define WHO_LEN 32 #define MAGIC_CRYPT_FIRST (0xac) static int cri_xx; #ifndef HIGHSCORE_MAX_KEEP #define HIGHSCORE_MAX_KEEP 10 #endif typedef struct { char seconds[4]; char uname[32]; char hitime[16]; } HolderTab; typedef struct { int en; /* enum EM_xxx */ HolderTab holders[HIGHSCORE_MAX_KEEP]; } HighScoreTab; static HighScoreTab high_score_tab[EM_Expert + 1] = { { EM_Beginner }, { EM_Intermidiate }, { EM_Expert }, }; static #ifdef __STDC__ void do_crypt(HighScoreTab* tab, int dir) #else do_crypt(tab, dir) /* dir=0:melt, 1:freeze */ HighScoreTab* tab; int dir; #endif { int i; int next_crip; char* p = (char*)tab; /* decrypt */ for (i = 0; i < sizeof *tab; ++i) { if (dir) next_crip = p[i]; p[i] ^= cri_xx; if (!dir) next_crip = p[i]; cri_xx = next_crip; } } void init_highscore(VOID) { int i; for (i = 0; i <= EM_Expert; ++i) { int j; for (j = 0; j < HIGHSCORE_MAX_KEEP; ++j) { strcpy(high_score_tab[i].holders[j].seconds, "999"); strcpy(high_score_tab[i].holders[j].uname, "unknown"); sprintf(high_score_tab[i].holders[j].hitime, "%0*ld", sizeof high_score_tab[i].holders[j].hitime - 1, 0); } } } void read_highscore(VOID) { FILE* fp = fopen(HIGH_SCORE_FILE, "r"); HighScoreTab tab; if (fp == NULL) { return; } cri_xx = MAGIC_CRYPT_FIRST; while (fread(&tab, sizeof tab, 1, fp)) { do_crypt(&tab, 0); memcpy(&high_score_tab[tab.en], &tab, sizeof tab); } fclose(fp); } void write_highscore(VOID) { FILE* fp = fopen(HIGH_SCORE_FILE, "w"); int i; if (fp == NULL) { perror(HIGH_SCORE_FILE); return; } cri_xx = MAGIC_CRYPT_FIRST; for (i = 0; i < sizeOf(high_score_tab); ++i) { HighScoreTab* p = high_score_tab + i; do_crypt(p, 1); fwrite(p, sizeof *p, 1, fp); } fclose(fp); } #define HI_MAGIC_STRING "MMMMMMMMMMMMMMMMMM" #define HI_MAGIC_LENGTH (sizeof HI_MAGIC_STRING) #define HI_OFFSET_STRING " " #define HI_OFFSET_LENGTH (sizeof HI_OFFSET_STRING) void ShowHighScore(VOID) { #define SHS_TITLE "Beginner Intermidiate Expert" int width = XTextWidth(fs, HI_OFFSET_STRING, HI_OFFSET_LENGTH) + XTextWidth(fs, HI_MAGIC_STRING, HI_MAGIC_LENGTH) * 7 / 2; XResizeWindow(d, highscore, width, menuheight * (HIGHSCORE_MAX_KEEP + 6)); XMapWindow(d, highscore); } void RedrawHighScore(VOID) { char buf[512]; int offset_x = XTextWidth(fs, HI_OFFSET_STRING, HI_OFFSET_LENGTH); static char* header[] = { "Beginner", "Intermidiate", "Expert" }; int i; int baseoffset; read_highscore(); XClearWindow(d, highscore); for (i = 0; i < HIGHSCORE_MAX_KEEP; ++i) { sprintf(buf, "%3d", i + 1); XDrawString(d, highscore, highscgc, offset_x, menuheight * (4 + i), buf, strlen(buf)); } baseoffset = XTextWidth(fs, buf, strlen(buf)) * 3 / 2; /* redraw each */ for (i = 0; i <= EM_Expert; ++i) { int j; int myoffset = offset_x + baseoffset + XTextWidth(fs, HI_MAGIC_STRING, HI_MAGIC_LENGTH) * i; XDrawString(d, highscore, highscgc, myoffset, menuheight * 2, header[i], strlen(header[i])); for (j = 0; j < HIGHSCORE_MAX_KEEP; ++j) { sprintf(buf, "%3.3s: %-8.8s", high_score_tab[i].holders[j].seconds, high_score_tab[i].holders[j].uname); XDrawString(d, highscore, highscgc, myoffset, menuheight * (4 + j), buf, strlen(buf)); } } #define CLICK_TO_CLOSE "Click this window to close" XDrawString(d, highscore, highscgc, baseoffset, menuheight * (5 + HIGHSCORE_MAX_KEEP), CLICK_TO_CLOSE, sizeof CLICK_TO_CLOSE - 1); } static int #ifdef __STDC__ highscore_compare(void* aa, void *bb) #else highscore_compare(aa, bb) char* aa; char* bb; #endif { HolderTab* a = (HolderTab*)aa; HolderTab* b = (HolderTab*)bb; int r = strcmp(a->seconds, b->seconds); if (r == 0) return b->seconds - a->seconds; return r; } void check_highscore(VOID) { if (mode < 0) /* ハイスコアに記録されないモード */ return; read_highscore(); if (atoi((char*)high_score_tab[mode].holders[HIGHSCORE_MAX_KEEP - 1].seconds) >= done - start) { sprintf(high_score_tab[mode].holders[HIGHSCORE_MAX_KEEP - 1].seconds, "%3.3d", done - start); strncpy(high_score_tab[mode].holders[HIGHSCORE_MAX_KEEP - 1].uname, getenv(appData.identifier), sizeof(high_score_tab[mode].holders[HIGHSCORE_MAX_KEEP - 1].uname)); sprintf(high_score_tab[mode].holders[HIGHSCORE_MAX_KEEP - 1].hitime, "%0*ld", sizeof high_score_tab[mode].holders[HIGHSCORE_MAX_KEEP - 1].hitime - 1, (long)time(NULL)); qsort(high_score_tab[mode].holders, HIGHSCORE_MAX_KEEP, sizeof high_score_tab[mode].holders[0], #ifdef __STDC__ (int (*)(const void*, const void*)) #endif highscore_compare); XStoreName(d, highscore, "!! NEW HIGH SCORE !!"); write_highscore(); ShowHighScore(); RedrawHighScore(); } } #endif