ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/hiscore.C
Revision: 1.30
Committed: Fri Nov 6 13:31:47 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_90, rel-2_92
Changes since 1.29: +0 -83 lines
Log Message:
remove or document dead code

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.23 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.18 *
4 root 1.26 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.20 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.18 *
8 root 1.27 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 pippijn 1.18 *
13 root 1.22 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.18 *
18 root 1.27 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 root 1.20 *
22 root 1.23 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.18 */
24 elmex 1.1
25     #include <global.h>
26 root 1.14 #include <sproto.h>
27 elmex 1.1
28     /*
29     * The score structure is used when treating new high-scores
30     */
31 root 1.5 typedef struct scr
32     {
33 root 1.9 char name[64]; // name */
34     char title[64]; // Title */
35     char killer[64]; // name (+ title) or "quit" */
36     sint64 exp; // Experience */
37     char maplevel[128]; // Killed on what level */
38     int maxhp, maxsp, maxgrace; // Max hp, sp, grace when killed */
39     int position; // Position in the highscore list */
40 elmex 1.1 } score;
41    
42     /*
43     * spool works mostly like strtok(char *, ":"), but it can also
44     * log a specified error message if something goes wrong.
45     */
46 root 1.29 static char *
47 root 1.19 spool (char *bp, const char *error)
48 root 1.5 {
49 elmex 1.1 static char *prev_pos = NULL;
50     char *next_pos;
51 root 1.5
52     if (bp == NULL)
53     {
54     if (prev_pos == NULL)
55     {
56     LOG (llevError, "Called spool (%s) with NULL without previous call.\n", error);
57     return NULL;
58     }
59     bp = prev_pos;
60     }
61     if (*bp == '\0')
62     {
63     LOG (llevError, "spool: End of line at %s\n", error);
64 elmex 1.1 return NULL;
65     }
66 root 1.5 if ((next_pos = strchr (bp, ':')) != NULL)
67     {
68     *next_pos = '\0';
69     prev_pos = next_pos + 1;
70     }
71     else
72 elmex 1.1 prev_pos = NULL;
73     return bp;
74     }
75    
76     /*
77     * Does what it says, copies the contents of the first score structure
78     * to the second one.
79     */
80 root 1.5 static void
81 root 1.6 copy_score (score *sc1, score *sc2)
82 root 1.5 {
83 root 1.7 assign (sc2->name , sc1->name);
84     assign (sc2->title , sc1->title);
85     assign (sc2->killer , sc1->killer);
86     assign (sc2->maplevel, sc1->maplevel);
87 root 1.5 sc2->exp = sc1->exp;
88     sc2->maxhp = sc1->maxhp;
89     sc2->maxsp = sc1->maxsp;
90     sc2->maxgrace = sc1->maxgrace;
91 elmex 1.1 }
92    
93     /*
94     * Writes the given score structure to a static buffer, and returns
95     * a pointer to it.
96     */
97 root 1.5 static char *
98 root 1.6 put_score (score *sc)
99 root 1.5 {
100 elmex 1.1 static char buf[MAX_BUF];
101 root 1.5
102 root 1.12 sprintf (buf, "%s:%s:%" PRId64 ":%s:%s:%d:%d:%d",
103     sc->name, sc->title, (sint64)sc->exp, sc->killer,
104     sc->maplevel, sc->maxhp, sc->maxsp, sc->maxgrace);
105 elmex 1.1 return buf;
106     }
107    
108     /*
109     * The oposite of put_score, get_score reads from the given buffer into
110     * a static score structure, and returns a pointer to it.
111     */
112    
113 root 1.5 static score *
114     get_score (char *bp)
115     {
116 elmex 1.1 static score sc;
117     char *cp;
118    
119 root 1.5 if ((cp = strchr (bp, '\n')) != NULL)
120     *cp = '\0';
121 elmex 1.1
122 root 1.5 if ((cp = spool (bp, "name")) == NULL)
123 root 1.7 return 0;
124    
125     assign (sc.name, cp);
126    
127     if ((cp = spool (0, "title")) == NULL)
128     return 0;
129    
130     assign (sc.title, cp);
131    
132     if ((cp = spool (0, "score")) == NULL)
133     return 0;
134 elmex 1.1
135 root 1.12 sscanf (cp, "%" SCNd64, &sc.exp);
136 root 1.5
137 root 1.7 if ((cp = spool (0, "killer")) == NULL)
138     return 0;
139    
140     assign (sc.killer, cp);
141    
142     if ((cp = spool (0, "map")) == NULL)
143     return 0;
144    
145     assign (sc.maplevel, cp);
146    
147     if ((cp = spool (0, "maxhp")) == NULL)
148     return 0;
149 elmex 1.1
150 root 1.5 sscanf (cp, "%d", &sc.maxhp);
151 elmex 1.1
152 root 1.7 if ((cp = spool (0, "maxsp")) == NULL)
153     return 0;
154    
155 root 1.5 sscanf (cp, "%d", &sc.maxsp);
156 elmex 1.1
157 root 1.7 if ((cp = spool (0, "maxgrace")) == NULL)
158     return 0;
159    
160 root 1.5 sscanf (cp, "%d", &sc.maxgrace);
161 elmex 1.1 return &sc;
162     }
163    
164 root 1.5 static char *
165 root 1.6 draw_one_high_score (score *sc)
166 root 1.5 {
167     static char retbuf[MAX_BUF];
168    
169     if (!strncmp (sc->killer, "quit", MAX_NAME))
170     sprintf (retbuf, "%3d %10lld %s the %s quit the game on map %s [%d][%d][%d].",
171     sc->position, (long long) sc->exp, sc->name, sc->title, sc->maplevel, sc->maxhp, sc->maxsp, sc->maxgrace);
172 root 1.25 else if (!strncmp (sc->killer, "leaving", MAX_NAME))
173 root 1.5 sprintf (retbuf, "%3d %10lld %s the %s left the game on map %s [%d][%d][%d].",
174     sc->position, (long long) sc->exp, sc->name, sc->title, sc->maplevel, sc->maxhp, sc->maxsp, sc->maxgrace);
175     else
176     sprintf (retbuf, "%3d %10lld %s the %s was killed by %s on map %s [%d][%d][%d].",
177     sc->position, (long long) sc->exp, sc->name, sc->title, sc->killer, sc->maplevel, sc->maxhp, sc->maxsp, sc->maxgrace);
178 root 1.25
179 root 1.5 return retbuf;
180     }
181 elmex 1.1
182     /*
183     * add_score() adds the given score-structure to the high-score list, but
184     * only if it was good enough to deserve a place.
185     */
186    
187 root 1.5 static score *
188 root 1.6 add_score (score *new_score)
189 root 1.5 {
190 elmex 1.1 FILE *fp;
191     static score old_score;
192 root 1.5 score *tmp_score, pscore[HIGHSCORE_LENGTH];
193 elmex 1.1 char buf[MAX_BUF], filename[MAX_BUF], *bp;
194 root 1.5 int nrofscores = 0, flag = 0, i, comp;
195    
196     new_score->position = HIGHSCORE_LENGTH + 1;
197     old_score.position = -1;
198     sprintf (filename, "%s/%s", settings.localdir, HIGHSCORE);
199     if ((fp = open_and_uncompress (filename, 1, &comp)) != NULL)
200     {
201     while (fgets (buf, MAX_BUF, fp) != NULL && nrofscores < HIGHSCORE_LENGTH)
202     {
203     if ((tmp_score = get_score (buf)) == NULL)
204     break;
205     if (!flag && new_score->exp >= tmp_score->exp)
206     {
207     copy_score (new_score, &pscore[nrofscores]);
208     new_score->position = nrofscores;
209     flag = 1;
210     if (++nrofscores >= HIGHSCORE_LENGTH)
211     break;
212     }
213     if (!strcmp (new_score->name, tmp_score->name))
214     { /* Another entry */
215     copy_score (tmp_score, &old_score);
216     old_score.position = nrofscores;
217     if (flag)
218     continue;
219     }
220     copy_score (tmp_score, &pscore[nrofscores++]);
221     }
222     close_and_delete (fp, comp);
223     }
224     if (old_score.position != -1 && old_score.exp >= new_score->exp)
225     return &old_score; /* Did not beat old score */
226     if (!flag && nrofscores < HIGHSCORE_LENGTH)
227     copy_score (new_score, &pscore[nrofscores++]);
228     if ((fp = fopen (filename, "w")) == NULL)
229     {
230     LOG (llevError, "Cannot write to highscore file %s: %s\n", filename, strerror (errno));
231     return NULL;
232     }
233     for (i = 0; i < nrofscores; i++)
234     {
235     bp = put_score (&pscore[i]);
236     fprintf (fp, "%s\n", bp);
237     }
238     fclose (fp);
239     if (flag)
240     {
241    
242 elmex 1.1 /* Eneq(@csd.uu.se): Patch to fix error in adding a new score to the
243     hiscore-list */
244 root 1.5 if (old_score.position == -1)
245     return new_score;
246     return &old_score;
247     }
248     new_score->position = -1;
249     if (old_score.position != -1)
250 elmex 1.1 return &old_score;
251 root 1.5 if (nrofscores)
252     {
253     copy_score (&pscore[nrofscores - 1], &old_score);
254     return &old_score;
255     }
256     LOG (llevError, "Highscore error.\n");
257 elmex 1.1 return NULL;
258     }
259    
260 root 1.5 void
261     check_score (object *op)
262     {
263     score new_score;
264     score *old_score;
265    
266     if (op->stats.exp == 0)
267     return;
268    
269 root 1.7 assign (new_score.name, op->name);
270     assign (new_score.title, op->title.length () ? &op->title : op->contr->title);
271 root 1.24 assign (new_score.killer, op->contr->killer_name ());
272 root 1.15 assign (new_score.maplevel, op->map ? op->map->name ? &op->map->name : &op->map->path : "");
273 root 1.7
274     new_score.exp = op->stats.exp;
275     new_score.maxhp = op->stats.maxhp;
276     new_score.maxsp = op->stats.maxsp;
277     new_score.maxgrace = op->stats.maxgrace;
278    
279 root 1.5 if ((old_score = add_score (&new_score)) == NULL)
280     {
281     new_draw_info (NDI_UNIQUE, 0, op, "Error in the highscore list.");
282     return;
283     }
284 root 1.7
285 root 1.5 if (new_score.position == -1)
286     {
287     new_score.position = HIGHSCORE_LENGTH + 1; /* Not strictly correct... */
288     if (!strcmp (old_score->name, new_score.name))
289     new_draw_info (NDI_UNIQUE, 0, op, "You didn't beat your last highscore:");
290     else
291     new_draw_info (NDI_UNIQUE, 0, op, "You didn't enter the highscore list:");
292     new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (old_score));
293     new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (&new_score));
294     return;
295     }
296 root 1.7
297 root 1.5 if (old_score->exp >= new_score.exp)
298     new_draw_info (NDI_UNIQUE, 0, op, "You didn't beat your last score:");
299     else
300     new_draw_info (NDI_UNIQUE, 0, op, "You beat your last score:");
301 elmex 1.1
302 root 1.5 new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (old_score));
303     new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (&new_score));
304 elmex 1.1 }
305