home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
1,000 Games
/
1000GAME.iso
/
games
/
bzone
/
c_scores.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-10
|
10KB
|
336 lines
#include "c_includ.h"
/*
* cbzone_scores.c
* -- Todd W Mummert, December 1990, CMU
*
* RCS Info
* $Header: c_scores.c,v 1.1 91/01/12 02:03:36 mummert Locked $
*
* Derived from work I did on our local version of golddig. Thanks
* to Bennet Yee (CMU) for the flock() code.
*/
/*
* Okay, let's try to clean this up. The following things may
* happen:
* score < 0: then the user is just asking for scores. the score
* file should not be changed.
* score >= 0: score is either valid, for practice, or played by an
* old version. In all cases, the file should change.
*
* file status:
* can be not there
* available for reading
* available for both reading and writing
* not there but can be written
*
* we know the following:
* whether the game was for practice only.
* any scores in the score file WILL be in the correct order.
*
* the format of the score file is as follows:
* Version identification
* number of games played, followed by number of valid games
* scores, one per line w/uid and player's name
*
* how should we go about comparing users?
* use getuid and cuserid...check both of them since we may be
* saving scores over a distributed file system
*
* if the game was scoresonly, print to tty if opt->output allows;
* else print to X screen.
*/
extern int errno;
int x, y, ydelta;
void xprintf(s, output) /* print to the X screen */
char* s;
Bool output;
{
printstring (x, y, s, strlen(s));
y += ydelta;
}
void nprintf(s, output) /* print to the parent tty */
char* s;
Bool output;
{
if (output)
printf("%s\n", s);
}
void printandwait(s, c) /* print a string and then */
char* s; /* wait for a character c */
char c; /* to be pressed. If c==0 */
{ /* then any keypress will */
y += ydelta; /* do. */
xprintf(s, True);
waitforkey(c);
}
LONG scores(score)
LONG score;
{
struct score_struct {
LONG score;
int uid;
char name[50];
struct score_struct *next;
} player, *current, *top_score, *prev_score;
FILE *sfile;
char buf[100];
char version[100];
char *login, *getlogin();
int i;
Font fontid;
int numgame = 0;
int numscore = 0;
int numscoreable = 0;
int player_scores = 0;
int tries = MAX_RETRIES;
Bool score_printed = False;
Bool scoresonly = False;
Bool wrong_version = False;
Bool file_readable = False;
Bool file_writeable = False;
Bool practice = opt->practice;
struct passwd* pw;
void (*p)();
version[0] ='\0';
if (score < 0) {
practice = True;
scoresonly = True;
p = nprintf;
}
else {
p = xprintf;
gprsetclippingactive(False);
fontid = gprloadfontfile(GAMEOVERFONT);
gprsettextfont(fontid);
printstring (165, 300, "GAME OVER", 9);
fontid = gprloadfontfile(GENERALFONT);
gprsettextfont(fontid);
printstring (165, 320, "1986 JSR", 8);
flushwindow();
sleep(1);
clearentirescreen();
}
x = 350;
y = 100;
ydelta = 15;
sprintf(buf,"%s%s",TANKDIR,SCOREFILE);
sfile = fopen(buf,"r"); /* just check if it is there */
if (sfile == NULL) {
p("Score file not readable.", opt->output);
if (scoresonly)
return 1;
else {
p("Will try and create new scorefile.", opt->output);
}
}
else
file_readable = True;
if (!scoresonly) {
(void) signal(SIGINT, SIG_IGN); /* no leaving this routine */
(void) signal(SIGHUP, SIG_IGN); /* no how, no way */
file_writeable = True;
if (sfile != NULL)
fclose(sfile);
retry:
if (file_readable)
sfile = fopen(buf,"r+"); /* okay, now open for update */
else
sfile = fopen(buf,"w");
if (sfile != NULL) {
if (flock(fileno(sfile),LOCK_EX) < 0) {
if (errno == EWOULDBLOCK && AFS) {
fclose(sfile);
sleep(AFS_SLEEP);
if (tries--)
goto retry;
}
p("File not lockable, scores will not be saved.", opt->output);
file_writeable = False;
}
}
else {
p("File not writeable, scores will not be saved.", opt->output);
file_writeable = False;
}
/* okay, it's possible we could have closed the file and never
* reopened it. Also, we just may not have been able to lock
* it. In either case, lets close it again and then open only
* for reading.
*/
if (file_readable && !file_writeable) {
if (sfile != NULL)
fclose(sfile);
if ((sfile = fopen(buf, "r")) == NULL)
file_readable = False;
}
}
if (!file_readable && !file_writeable) {
p("Scorefile not readable or writeable...Goodbye!", opt->output);
(void) signal(SIGINT, SIG_DFL); /* this would probably happen */
(void) signal(SIGHUP, SIG_DFL); /* on exit anyway */
if (!scoresonly)
printandwait("Press any key to continue...", 0);
return 1;
}
if (file_readable) {
if(fgets(version,200,sfile) && file_writeable) {
version[strlen(version)-1] = '\0'; /* strip the newline */
if (strcmp(version,VERSION)) {
wrong_version = True;
p("Incorrect version played for this scorefile.", opt->output);
p("Score not valid for inclusion.", opt->output);
sprintf(buf,"Your version is \"%s\", while",VERSION);
p(buf, opt->output);
sprintf(buf, " the scorefile version is \"%s\"", version);
p(buf, opt->output);
}
}
if (*version == '\0')
strcpy(version,VERSION);
if(fgets(buf,200,sfile))
sscanf(buf,"%d %d",&numgame,&numscoreable);
top_score = (struct score_struct*) malloc(sizeof(struct score_struct));
current = top_score;
while(fgets(buf,200,sfile) && numscore < NUMHIGH)
if (sscanf(buf,"%d %d %[^\n]",¤t->score,
¤t->uid,current->name) != 3) {
p("Invalid line in score file...Skipping.", opt->output);
}
else {
current->next = (struct score_struct*)
malloc(sizeof(struct score_struct));
prev_score = current;
current = current->next;
numscore ++;
}
}
if (numscore)
prev_score->next = NULL;
else
top_score = NULL;
if (numgame < numscoreable)
numgame = numscoreable;
if (!scoresonly) {
/* try to get it from the passwd file first, just in case this
* person su'd from another acct.
*/
player.uid = getuid();
player.score = score;
pw = getpwuid(player.uid);
if (pw == NULL)
if ((login = getlogin()) != NULL)
strcpy(player.name, login);
else {
p("Can't find out who you are....bye.", opt->output);
fclose(sfile);
(void) signal(SIGINT, SIG_DFL);
(void) signal(SIGHUP, SIG_DFL);
if (!scoresonly)
printandwait("Press any key to continue...", 0);
return 1;
}
else
strcpy(player.name, pw->pw_name);
if (numscore < NUMHIGH || player.score > prev_score->score) {
score_printed = True;
numscore++;
for (current = top_score;
current != NULL && player.score <= current->score;
prev_score = current, current = current->next);
player.next = current;
if (current == top_score)
top_score = &player;
else
prev_score->next = &player;
}
numgame++;
if (!practice && !wrong_version)
numscoreable++;
}
sprintf(buf, "High scores after %d games, %d scoreable:",
numgame, numscoreable);
p(buf, opt->output);
current = top_score;
while (current != NULL) {
if (current == &player)
*buf = '>';
else
*buf = ' ';
sprintf(buf+1, "%-20s %8d", current->name, current->score);
p(buf, opt->output);
if (((wrong_version || practice) && current==&player) ||
(current->uid==player.uid && !strcmp(player.name, current->name) &&
++player_scores>INDIVIDUAL_SCORES)) {
numscore--;
if (current == top_score)
top_score = current->next;
else
prev_score->next = current->next;
}
else
prev_score = current;
current = current->next;
}
if (!scoresonly && !score_printed) {
p("...", opt->output);
sprintf(buf, ">%-20s %8d", player.name,player.score);
p(buf, opt->output);
}
if (file_writeable) {
rewind(sfile);
fprintf(sfile,"%s\n",version);
fprintf(sfile,"%d %d\n",numgame,numscoreable);
for(current = top_score, i = 0;
current != NULL && i < NUMHIGH;
current = current->next, i++)
fprintf(sfile,"%d %d %s\n",current->score,current->uid,current->name);
if (practice) {
y += ydelta;
p("Your game was for practice only...", opt->output);
p("For a valid score use: cbzone [-q] [-d 0-5]", opt->output);
}
}
fclose(sfile);
(void) signal(SIGINT, SIG_DFL);
(void) signal(SIGHUP, SIG_DFL);
if (!scoresonly)
printandwait("Press any key when ready...", 0);
return 0;
}