1 /* file scores.c */
2 /***************************************************************************
3 * Copyright 2003 - Steven Shipway <steve@cheshire.demon.co.uk> *
4 * Put "nospam" in subject to avoid spam filter *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA *
19 * 02111-1307, USA. *
20 ***************************************************************************/
21
22
23 #include "wand_head.h"
24
25 #ifdef MSDOS /* M001 */
26
27 #define LOCK
28 #define UNLOCK
29
30 #else
31 /*#define LOCK flock( fp->_cnt , LOCK_EX ) /* peeked at stdio.h ! */
32 /*#define UNLOCK flock( fp->_cnt , LOCK_UN ) /* */
33 /* #define LOCK while((lock = creat(LOCKFILE,0))==-1) Not a good way */
34
35 #define LOCK if((lock = open(LOCKFILE, O_CREAT | O_TRUNC | O_WRONLY, "r"))==-1){errx (1,"%s","Lockfile creation failed\n"); exit(1);} /* Marina */
36
37 #define UNLOCK unlink(LOCKFILE)
38
39 #endif
40
41 #ifndef MSDOS /* M001 */
42 extern int getuid();
43 #else
44 #define getuid() 0
45 #endif
46
47 #ifdef COMPARE_BY_NAME
48 #define SAMEUSER(p) (strcmp((p)->name, name) == 0)
49 #else
50 #define SAMEUSER(p) ((p)->uid == user_id)
51 #endif
52
53 extern int saved_game; /* prevent recording of hiscore if */
54 /* NO_RESTORED_GAME_HISCORES is #def'd */
55
56 /***********************************
57 * score_entry structure *
58 ************************************/
59 typedef struct
60 {
61 char howdead[25];
62 char name[20];
63 int score;
64 int level;
65 int uid;
66 } score_entry;
67
68 #ifdef LINT_ARGS /* M001 */
69 void show_scores(score_entry *,int );
70 int readtable(score_entry *);
71 #else
72 void show_scores();
73 int readtable();
74 #endif
75
76 /**/
77 /************************
78 * show_scores *
79 *************************/
show_scores(score_entry * table,int num)80 void show_scores(score_entry *table,int num)
81 {
82 int tot = num;
83
84 printf("\nNo. Score Level Names How they died\n");
85 printf("=============================================================================\n");
86 while(num > 0)
87 {
88 num--;
89 printf("%2d %5d %3d %-20s killed by %-s\n",(tot - num),table->score,table->level,table->name,table->howdead);
90 table++;
91 }
92 printf("\n\n");
93 }
94
95 /**/
96 /*************************
97 * readtable function *
98 **************************/
readtable(score_entry * table_ptr)99 int readtable(score_entry *table_ptr)
100 {
101 FILE *fp;
102 int numread;
103
104 if((fp = fopen(HISCOREPATH,R_BIN)) == NULL)
105 {
106 numread = 0;
107 }
108 else
109 {
110 numread = fread( VOIDSTAR table_ptr, sizeof(score_entry), ENTRIES, fp);
111 fclose(fp);
112 }
113 return numread;
114 }
115
116 /**/
117 /********************
118 * savescore *
119 *********************/
120
savescore(char * howdead,int score,int level,char * name)121 int savescore(char *howdead,int score,int level,char *name)
122 {
123 score_entry table[ENTRIES + 2],
124 *table_ptr = table,
125 new_entry,
126 temp_entry;
127 int numread;
128 int index = 1;
129 int numsaved;
130 int lock;
131 int already = 0;
132 int output_value = 1;
133 int user_id;
134 int position;
135
136 FILE *fp;
137
138 #ifdef NO_RESTORED_GAME_HISCORES
139
140 if(saved_game)
141 {
142 printf("No hiscores recorded from restored games.\n");
143 printf("\nWanderer (C) 1988 S.Shipway.\n\n");
144 return 1;
145 }
146 #endif
147
148 user_id = getuid();
149 strncpy(new_entry.howdead,howdead,25);
150 new_entry.howdead[24] = '\0'; /* M002 strncpy does not null terminate */
151 strncpy(new_entry.name,name,20);
152 new_entry.name[19] = '\0'; /* M002 strncpy does not null terminate */
153 new_entry.score = score;
154 new_entry.level = level;
155 new_entry.uid = user_id;
156 LOCK; /* BUG is HERE !!! */
157 numread = readtable(table_ptr);
158 if (numread > 0)
159 if(table[numread-1].score > 99999) /* stop system errors messing it up*/
160 {
161 numread--;
162 printf("Erasing spurious entry in table.\n");
163 }
164 if(score == -1)
165 {
166 show_scores(table,numread);
167 UNLOCK;
168 return 0;
169 }
170 /* HERE */
171 if (numread > 0)
172 {
173 numread++; /* scan through until correct insertion point */
174 /* pass table entries with higher scores */
175 while((table_ptr->score > score)&&(index < numread))
176 {
177 if(SAMEUSER(table_ptr))
178 {
179 already = 1;
180 break;
181 }
182 table_ptr++;
183 index++;
184 }
185 /* pass table entries with equal score but higher or equal level */
186
187 while((table_ptr->level>=level)&&
188 (index<numread)&&
189 (table_ptr->score==score))
190 {
191 if(SAMEUSER(table_ptr))
192 {
193 already = 1;
194 break;
195 }
196 table_ptr++;
197 index++;
198 }
199 position = index;
200 /* if already found: done */
201 if(already == 1)
202 {
203 numread--;
204 UNLOCK;
205 return numread;
206 }
207 /* shift down score list */
208 while(index < numread)
209 {
210 /* swap *table_ptr and new_entry */
211 temp_entry = *table_ptr;
212 *table_ptr = new_entry;
213 new_entry = temp_entry;
214 if(SAMEUSER(&new_entry))
215 {
216 already = 1;
217 numread--; /* an older entry found */
218 break;
219 }
220 table_ptr++;
221 index++;
222 }
223 /* if all shifted without finding an older entry */
224 if(already==0)
225 *table_ptr = new_entry;
226 if( position <= ENTRIES )
227 printf("You rank %d in the hiscore table.\n",position);
228 else
229 printf("Sorry, you didnt make it into the hiscore table this time.\n");
230 }
231 else
232 {
233 printf("\nCreating new hiscore table.\n\n");
234 *table_ptr = new_entry;
235 numread++;
236 }
237 numread = ( (numread > ENTRIES) ? ENTRIES : numread );
238
239 if((fp = fopen(HISCOREPATH,W_BIN)) != NULL)
240 {
241 table_ptr = table;
242 numsaved = fwrite(VOIDSTAR table_ptr, sizeof(score_entry), numread, fp);
243 chmod(HISCOREPATH,0666);
244 if(numsaved < numread)
245 {
246 printf("ERROR! Only %d items saved from %d !\n",numsaved,numread);
247 output_value = 0;
248 }
249 fclose(fp);
250 }
251 else
252 err(1,"%s","Error in savescore - fopen HISCOREPATH failed\n");
253
254 UNLOCK;
255 return output_value;
256 }
257
258 /**/
259 /*************************
260 * delete_entry *
261 **************************/
delete_entry(int num)262 void delete_entry(int num)
263 {
264 score_entry table[ENTRIES + 22],
265 *table_ptr = table,
266 new_entry,temp_entry;
267 int numread,index = 1, numsaved, lock, output_value = 1;
268 FILE *fp;
269
270 LOCK;
271 numread = readtable(table_ptr);
272 if (numread == 0) {
273 printf("Missing or unreadable hiscore table.\n\n");
274 UNLOCK;
275 exit(1);
276 }
277 if (num > numread) {
278 printf("Invalid entry, choose again\n");
279 UNLOCK;
280 return;
281 }
282 while(index < num)
283 {
284 index++;
285 table_ptr++;
286 }
287 while(index < numread)
288 {
289 index++;
290 *table_ptr = *(table_ptr+1);
291 table_ptr++;
292 }
293 numread--;
294
295 if((fp = fopen(HISCOREPATH,W_BIN)) != NULL)
296 {
297 table_ptr = table;
298 numsaved = fwrite(VOIDSTAR table_ptr, sizeof(score_entry), numread, fp);
299 chmod(HISCOREPATH,0666);
300 if(numsaved < numread)
301 {
302 printf("ERROR! Only %d items saved from %d !\n",numsaved,numread);
303 output_value = 0;
304 }
305 fclose(fp);
306 }
307 else
308 err(1, "%s", "Could not open Scorefile\n");
309 UNLOCK;
310 show_scores(table,numsaved);
311 }
312
313 /**/
314 /************************
315 * erase_scores *
316 *************************/
erase_scores()317 erase_scores()
318 {
319 int erasenum;
320 int numread;
321 int index = 0;
322 char correct[20], c;
323 score_entry table[ENTRIES + 2], *table_ptr = table;
324
325 printf("Please enter password:");
326 while((c = getchar()) != '\n' && index <19)
327 {
328 correct[index++] = c;
329 }
330 correct[index] = 0;
331 if(strcmp(correct,MASTERPASSWORD))
332 {
333 printf("\nFoo, charlatan!\n");
334 return 0;
335 }
336 numread = readtable(table_ptr);
337 show_scores(table,numread);
338 printf("\n");
339
340 for(;;)
341 {
342 printf("Number to erase (0 to exit): ");
343 scanf("%d",&erasenum);
344 printf("\n");
345 if(erasenum == 0)
346 break;
347 delete_entry(erasenum);
348 printf("\n");
349 }
350 printf("Byee!\n");
351 }
352