1 /***************************************************************************
2 score.c - description
3 -------------------
4 begin : Sat Jan 1 2000
5 copyright : (C) 2000 by Perdig
6 email : perdig@linuxbr.com.br
7
8 $Id: score.c,v 1.6 2001/01/01 18:49:16 perdig Exp $
9 ***************************************************************************/
10
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20 #include <string.h>
21 #include "config.h"
22 #include "score.h"
23 #include "time.h"
24
25 #define MAXHISCORE 20
26
27 hiScoreStruct hiscore;
28
29 #define addMember(member, string) do { \
30 hiscoreTemp = member; \
31 member = (hiMemberStruct *)malloc(sizeof(hiMemberStruct)); \
32 member->name = string; \
33 member->child = NULL; \
34 member->next = hiscoreTemp; } while (0)
35
36 bool useGAMEDIR = true;
37 time_t startime;
38
39 extern int lives;
40 extern char livesString[10];
41
lookup(hiMemberStruct * member,char * name)42 hiMemberStruct *lookup(hiMemberStruct *member, char *name) {
43 while (member != NULL && strcmp(member->name, name) != 0) {
44 member = member->next;
45 }
46 return member;
47 }
48
numElements(hiMemberStruct * member)49 int numElements(hiMemberStruct *member) {
50 int a = 0;
51 while (member != NULL) {
52 a++;
53 member = member->next;
54 }
55 return a;
56 }
57
loadRecords(char * filename)58 void loadRecords(char *filename) {
59 FILE *fd;
60 char buf[256] = "";
61 char *temp = NULL;
62 hiMemberStruct *hiscoreTemp;
63 // Look first for a global hiscore
64 temp = (char *)malloc(256);
65 getcwd(temp, 256);
66 chdir(GAMEDIR);
67 fd = fopen(filename, "r");
68 if (fd == NULL) {
69 useGAMEDIR = false;
70 chdir(temp);
71 dbg("%s...", temp);
72 fd = fopen(filename, "r");
73 if (fd == NULL) {
74 dbg("can't find a hiscore file. Creating a new one at %s...", temp);
75 return;
76 }
77 } else {
78 dbg("%s...", GAMEDIR);
79 }
80 chdir(temp);
81 free(temp);
82 temp = NULL;
83
84 while(fgets(buf, 256, fd)) {
85 temp = (char *)malloc(strlen(buf-2));
86 strcpy(temp, buf+2);
87 temp[ strlen(temp)-1 ] = 0;
88 switch (*buf) {
89 case '*':
90 addMember(hiscore.level, temp);
91 break;
92 case '+':
93 addMember(hiscore.level->child, temp);
94 break;
95 case '-':
96 addMember(hiscore.level->child->child, temp);
97 break;
98 }
99 }
100 }
101
newRecord(levelStruct * level,scoreStruct * score)102 bool newRecord(levelStruct *level, scoreStruct *score) {
103 int record;
104 hiMemberStruct *it;
105 // If 0 points, don't even care
106 if (score->value <= 0)
107 return false;
108
109 // Lookup level
110 it = lookup(hiscore.level, level->name);
111
112 // Lookup variation
113 if (it == NULL) {
114 // No level!
115 return true;
116 }
117 it = lookup(it->child, level->sum);
118 if (it == NULL) {
119 // No var!
120 return true;
121 }
122 it = it->child;
123 if (numElements(it) < MAXHISCORE)
124 return true;
125 else {
126 while (it->next != NULL)
127 it = it->next;
128 sscanf(it->name, "%d", &record);
129 return score->value > record;
130 }
131 }
132
addRecord(levelStruct * level,scoreStruct * score,char * name)133 int addRecord(levelStruct *level, scoreStruct *score, char *name) {
134 int record = score->value+1;
135 hiMemberStruct *itL, *itV, *itR;
136 hiMemberStruct *hiscoreTemp;
137 char *temp;
138 char livStr[16];
139 char date[256];
140 int pos = 1;
141 bool first = false;
142 time_t curtime;
143 ldbg("Adding record of %d by %s", score->value, name);
144 // Create string
145 curtime = time(0);
146 strftime(date, 256, "%m/%d/%Y", localtime(&curtime));
147 temp = (char *)malloc(256);
148 if (lives >= 0)
149 sprintf(livStr, "%d lives", lives);
150 else
151 sprintf(livStr, "Died");
152 sprintf(temp, "%d %s (%s - %ld min:%ld sec) %s", score->value, name, livStr, (curtime-startime)/60, (curtime-startime)%60, date);
153 // Find level
154 itL = lookup(hiscore.level, level->name);
155 if (itL == NULL) {
156 // No level by that name! Create new
157 addMember(hiscore.level, level->name);
158 itL = hiscore.level;
159 }
160 // Find sum
161 itV = lookup(itL->child, level->sum);
162 if (itV == NULL) {
163 // No of that sum! Create new
164 addMember(itL->child, level->sum);
165 itV = itL->child;
166 }
167 itR = itV->child;
168 if (itR == NULL) {
169 // No record yet! Create new
170 addMember(itV->child, temp);
171 return 0;
172 }
173 sscanf(itR->name, "%d", &record);
174 if (record < score->value)
175 first = true;
176 while (itR->next) {
177 sscanf(itR->next->name, "%d", &record);
178 if (record < score->value)
179 break;
180 pos++;
181 itR = itR->next;
182 }
183 // 'itR' now holds a pointer to the right place.
184 hiscoreTemp = (hiMemberStruct *)malloc(sizeof(hiMemberStruct));
185 hiscoreTemp->next = first ? itR : itR->next;
186 hiscoreTemp->child = NULL;
187 hiscoreTemp->name = temp;
188 if (!first)
189 itR->next = hiscoreTemp;
190 else
191 itV->child = hiscoreTemp;
192 // Erases those who are extra
193 itR = itV->child;
194 while (numElements(itR) > MAXHISCORE) {
195 itR = itV->child;
196 if (!itR->next)
197 break;
198 while (itR->next->next != NULL)
199 itR = itR->next;
200 itR->next = NULL;
201 }
202
203 return first ? 0 : pos;
204 }
205
getRecord(levelStruct * level)206 char *getRecord(levelStruct *level) {
207 hiMemberStruct *itLev;
208 hiMemberStruct *itVar;
209 unsigned int val;
210 char *name = NULL;
211 char *retval = NULL;
212 for (itLev = hiscore.level; itLev; itLev = itLev->next) {
213 if (strcmp(level->name, itLev->name)==0) {
214 for (itVar = itLev->child; itVar; itVar = itVar->next) {
215 if (strcmp(level->sum, itVar->name)==0) {
216 name = itVar->child->name;
217 break;
218 }
219 }
220 }
221 }
222 if (name) {
223 retval = (char *)malloc(SCORE_DIGITS*sizeof(char));
224 sscanf(name, "%u", &val);
225 sprintf(retval, "%.*u", SCORE_DIGITS-1, val);
226 }
227
228 return retval;
229
230 }
231
listRecords(levelStruct * level)232 char **listRecords(levelStruct *level) {
233 hiMemberStruct *itLev;
234 hiMemberStruct *itVar;
235 hiMemberStruct *itVal;
236 char **values = NULL;
237 int a;
238
239 ldbg("Starting to display high scores now!");
240 for (itLev = hiscore.level; itLev; itLev = itLev->next) {
241 if (strcmp(level->name, itLev->name)==0) {
242 for (itVar = itLev->child; itVar; itVar = itVar->next) {
243 if (strcmp(level->sum, itVar->name)==0) {
244 values = (char **)calloc(numElements(itVar->child)+1, sizeof(char *));
245 values[0] = (char *)malloc(sizeof(char));
246 *values[0] = (char )numElements(itVar->child);
247 for (itVal = itVar->child, a = 1; itVal; itVal = itVal->next, a++) {
248 values[a] = itVal->name;
249 }
250 }
251 }
252 }
253 }
254 return values;
255 }
256
saveRecords(char * filename)257 void saveRecords(char *filename) {
258 FILE *fd;
259 char *temp = NULL;
260 hiMemberStruct *itL, *itV, *itR;
261 if (useGAMEDIR) {
262 temp = (char *)malloc(256);
263 getcwd(temp, 256);
264 chdir(GAMEDIR);
265 }
266 fd = fopen(filename, "w");
267 if (!fd) {
268 perror("Can't create new file");
269 return;
270 }
271 if (useGAMEDIR) {
272 chdir(temp);
273 free(temp);
274 temp = NULL;
275 }
276 // Stores the values in inverse order
277 // Also erases everything
278 for (itL = hiscore.level; itL; itL = itL->next) {
279 // Writes the level
280 fprintf(fd, "* %s\n", itL->name);
281 for (itV = itL->child; itV; itV = itV->next) {
282 fprintf(fd, "+ %s\n", itV->name);
283 itR = itV->child;
284 // Ok, now saves it
285 while (itR != NULL) {
286 itR = itV->child;
287 if (itR->next == NULL) {
288 fprintf(fd, "- %s\n", itR->name);
289 break;
290 }
291 // Puts itR at the end
292 while (itR->next->next != NULL)
293 itR = itR->next;
294 // itR->next is the last one! Write it down
295 fprintf(fd, "- %s\n", itR->next->name);
296 // Now erases it
297 free(itR->next);
298 itR->next = NULL;
299 // Go to next one
300 }
301 }
302 }
303 fclose(fd);
304 }
305
add_score(scoreStruct * score,levelStruct * level,int value)306 void add_score(scoreStruct *score, levelStruct *level, int value) {
307 while (value > 0) {
308 score->value++;
309 value--;
310 if (score->value >= score->current_extra && score->current_extra > 0) {
311 lives++;
312 sprintf(livesString, "Lives: %d", lives);
313 score->num_extra++;
314 score->current_extra += score->num_extra*level->extra;
315 score->timer+=128;
316 }
317 }
318 sprintf(score->string, "%.*u", SCORE_DIGITS - 1, score->value);
319 }
320