1 #include <stdio.h>
2 #include <signal.h>
3 #include "sokoban.h"
4 
5 extern FILE *fopen();
6 
7 extern char  *username;
8 extern short scorelevel, scoremoves, scorepushes;
9 
10 static short scoreentries;
11 static struct {
12    char user[MAXUSERNAME];
13    short lv, mv, ps;
14 } scoretable[MAXSCOREENTRIES];
15 
16 static FILE *scorefile;
17 static int sfdbn;
18 
outputscore()19 short outputscore() {
20 
21    short ret;
22 
23    while( access(LOCKFILE,0) != -1);	/* lock the score file */
24    creat(LOCKFILE,0666);
25    if( (ret = readscore()) == 0)
26       showscore();
27    unlink( LOCKFILE);
28    return( (ret == 0) ? E_ENDGAME : ret);
29 }
30 
newscore()31 short newscore() {
32 
33    short ret = 0;
34 
35    while( access(LOCKFILE) != -1) ;
36    creat(LOCKFILE,0666);
37    scoreentries = 0;
38    if( (scorefile = fopen( SCOREFILE, "w")) == NULL)
39       ret = E_FOPENSCORE;
40    else {
41       sfdbn = fileno( scorefile);
42       if( write( sfdbn, &scoreentries, 2) != 2) ret = E_WRITESCORE;
43       fclose( scorefile);
44    }
45    unlink( LOCKFILE);
46    return( (ret == 0) ? E_ENDGAME : ret);
47 }
48 
getuserlevel(lv)49 short getuserlevel( lv)
50 short *lv;
51 {
52    short ret = 0, pos;
53 
54    while( access( LOCKFILE) != -1);
55    creat(LOCKFILE,0666);
56    if( (scorefile = fopen( SCOREFILE, "r")) == NULL)
57       ret = E_FOPENSCORE;
58    else {
59       if( (ret = readscore()) == 0)
60 	 *lv = ( (pos = finduser()) > -1) ? scoretable[pos].lv+1 : 1;
61    }
62    unlink( LOCKFILE);
63    return( ret);
64 }
65 
score()66 short score() {
67 
68    short ret;
69 
70    while( access( LOCKFILE) != -1);
71    creat(LOCKFILE,0666);
72    if( (ret = readscore()) == 0)
73       if( (ret = makescore()) == 0)
74 	 if( (ret = writescore()) == 0)
75 	    showscore();
76    unlink( LOCKFILE);
77    return( (ret == 0) ? E_ENDGAME : ret);
78 }
79 
readscore()80 readscore() {
81 
82    short ret = 0;
83    int tmp;
84 
85    if( (scorefile = fopen( SCOREFILE, "r")) == NULL)
86       ret = E_FOPENSCORE;
87    else {
88       sfdbn = fileno( scorefile);
89       if( read( sfdbn, &scoreentries, 2) != 2) ret = E_READSCORE;
90       else {
91 	 tmp = scoreentries * sizeof( scoretable[0]);
92 	 if( read( sfdbn, &(scoretable[0]), tmp) != tmp) ret = E_READSCORE;
93       }
94       fclose( scorefile);
95    }
96    return( ret);
97 }
98 
makescore()99 makescore() {
100 
101    short ret = 0, pos, i, build = 1, insert;
102 
103    if( (pos = finduser()) > -1) {	/* user already in score file */
104       insert =    (scorelevel > scoretable[pos].lv)
105 	       || ( (scorelevel == scoretable[pos].lv) &&
106                     (scoremoves < scoretable[pos].mv)
107 		  )
108 	       || ( (scorelevel == scoretable[pos].lv) &&
109 		    (scoremoves == scoretable[pos].mv) &&
110 		    (scorepushes < scoretable[pos].ps)
111 		  );
112       if( insert) { 			/* delete existing entry */
113 	 for( i = pos; i < scoreentries-1; i++)
114 	    cp_entry( i, i+1);
115 	 scoreentries--;
116       }
117       else build = 0;
118    }
119    else if( scoreentries == MAXSCOREENTRIES)
120       ret = E_TOMUCHSE;
121    if( (ret == 0) && build) {
122       pos = findpos();			/* find the new score position */
123       if( pos > -1) {			/* score table not empty */
124 	 for( i = scoreentries; i > pos; i--)
125 	    cp_entry( i, i-1);
126       }
127       else pos = scoreentries;
128 
129       strcpy( scoretable[pos].user, username);
130       scoretable[pos].lv = scorelevel;
131       scoretable[pos].mv = scoremoves;
132       scoretable[pos].ps = scorepushes;
133       scoreentries++;
134    }
135    return( ret);
136 }
137 
finduser()138 finduser() {
139 
140    short i, found = 0;
141 
142    for( i = 0; (i < scoreentries) && (! found); i++)
143       found = (strcmp( scoretable[i].user, username) == 0);
144    return( (found) ? i-1 : -1);
145 }
146 
findpos()147 findpos() {
148 
149    short i, found = 0;
150 
151    for( i = 0; (i < scoreentries) && (! found); i++)
152       found =    (scorelevel > scoretable[i].lv)
153 	      || ( (scorelevel == scoretable[i].lv) &&
154                    (scoremoves < scoretable[i].mv)
155 		 )
156 	      || ( (scorelevel == scoretable[i].lv) &&
157 		   (scoremoves == scoretable[i].mv) &&
158 		   (scorepushes < scoretable[i].ps)
159 		 );
160    return( (found) ? i-1 : -1);
161 }
162 
writescore()163 writescore() {
164 
165    short ret = 0;
166    long tmp;
167 
168    if( (scorefile = fopen( SCOREFILE, "w")) == NULL)
169       ret = E_FOPENSCORE;
170    else {
171       sfdbn = fileno( scorefile);
172       if( write( sfdbn, &scoreentries, 2) != 2) ret = E_WRITESCORE;
173       else {
174 	 tmp = scoreentries * sizeof( scoretable[0]);
175 	 if( write( sfdbn, &(scoretable[0]), tmp) != tmp) ret = E_WRITESCORE;
176       }
177       fclose( scorefile);
178    }
179    return( ret);
180 }
181 
showscore()182 showscore() {
183 
184    register short lastlv = 0, lastmv = 0, lastps = 0, i;
185 
186    fprintf( stdout, "Rank        User     Level     Moves    Pushes\n");
187    fprintf( stdout, "==============================================\n");
188    for( i = 0; i < scoreentries; i++) {
189       if( (scoretable[i].lv == lastlv)&&
190 	  (scoretable[i].mv == lastmv) &&
191 	  (scoretable[i].ps == lastps))
192 	 fprintf( stdout, "      ");
193       else {
194          lastlv = scoretable[i].lv;
195          lastmv = scoretable[i].mv;
196          lastps = scoretable[i].ps;
197          fprintf( stdout, "%4d  ", i+1);
198       }
199       fprintf( stdout, "%10s  %8d  %8d  %8d\n", scoretable[i].user,
200 		scoretable[i].lv, scoretable[i].mv, scoretable[i].ps);
201    }
202 }
203 
cp_entry(i1,i2)204 cp_entry( i1, i2)
205 register short i1, i2;
206 {
207    strcpy( scoretable[i1].user, scoretable[i2].user);
208    scoretable[i1].lv = scoretable[i2].lv;
209    scoretable[i1].mv = scoretable[i2].mv;
210    scoretable[i1].ps = scoretable[i2].ps;
211 }
212