ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.5
Committed: Fri Mar 26 00:59:20 2010 UTC (14 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +2 -2 lines
Log Message:
remove bogus 2007 copyright that was added wrongly by the script, update to affero license

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3     *
4     * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992 Frank Tore Johansen
7 root 1.1 *
8     * 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     *
13     * 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     *
18     * 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     *
22     * The authors can be reached via e-mail to <support@deliantra.net>
23     */
24    
25     /*
26     * compatibility functions for older (GPL) source code parts
27     */
28    
29     #include <cstring>
30     #include <assert.h>
31     #include <stdio.h>
32     #include <string.h>
33     #include <limits.h>
34    
35     #include <global.h>
36     #include "define.h"
37     #include "path.h"
38    
39    
40     /* buf_overflow() - we don't want to exceed the buffer size of
41     * buf1 by adding on buf2! Returns true if overflow will occur.
42     */
43     int
44     buf_overflow (const char *buf1, const char *buf2, int bufsize)
45     {
46     int len1 = 0, len2 = 0;
47    
48     if (buf1)
49     len1 = strlen (buf1);
50    
51     if (buf2)
52     len2 = strlen (buf2);
53    
54     if ((len1 + len2) >= bufsize)
55     return 1;
56    
57     return 0;
58     }
59    
60     /////////////////////////////////////////////////////////////////////////////
61    
62     static const char *const fatalmsgs[80] = {
63     "Failed to allocate memory",
64     "Failed repeatedly to load maps",
65     "Hashtable for archetypes is too small",
66     "Too many errors"
67     };
68    
69     /*
70     * fatal() is meant to be called whenever a fatal signal is intercepted.
71     * It will call the emergency_save and the clean_tmp_files functions.
72     */
73     void
74     fatal (int err)
75     {
76     LOG (llevError, "Fatal: %s\n", fatalmsgs [err]);
77     cleanup (fatalmsgs[err], 1);
78     }
79    
80     /////////////////////////////////////////////////////////////////////////////
81    
82     /*
83     * The random functions here take luck into account when rolling random
84     * dice or numbers. This function has less of an impact the larger the
85     * difference becomes in the random numbers. IE, the effect is lessened
86     * on a 1-1000 roll, vs a 1-6 roll. This can be used by crafty programmers,
87     * to specifically disable luck in certain rolls, simply by making the
88     * numbers larger (ie, 1d1000 > 500 vs 1d6 > 3)
89     */
90    
91     /*
92     * Roll a random number between min and max. Uses op to determine luck,
93     * and if goodbad is non-zero, luck increases the roll, if zero, it decreases.
94     * Generally, op should be the player/caster/hitter requesting the roll,
95     * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
96     */
97     int
98     random_roll (int r_min, int r_max, const object *op, int goodbad)
99     {
100     r_max = max (r_min, r_max);
101    
102     int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */
103    
104     if (op->type == PLAYER)
105     {
106     int luck = op->stats.luck;
107    
108     if (rndm (base) < min (10, abs (luck)))
109     {
110     //TODO: take luck into account
111     }
112     }
113    
114     return rndm (r_min, r_max);
115     }
116    
117     /*
118     * This is a 64 bit version of random_roll above. This is needed
119     * for exp loss calculations for players changing religions.
120     */
121     sint64
122     random_roll64 (sint64 r_min, sint64 r_max, const object *op, int goodbad)
123     {
124     sint64 omin = r_min;
125     sint64 range = max (0, r_max - r_min + 1);
126     int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
127    
128     /*
129     * Make a call to get two 32 bit unsigned random numbers, and just to
130     * a little bitshifting.
131     */
132     sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31);
133    
134     if (op->type != PLAYER)
135     return ((ran % range) + r_min);
136    
137     int luck = op->stats.luck;
138    
139     if (rndm (base) < min (10, abs (luck)))
140     {
141     /* we have a winner */
142     ((luck > 0) ? (luck = 1) : (luck = -1));
143     range -= luck;
144     if (range < 1)
145     return (omin); /*check again */
146    
147     ((goodbad) ? (r_min += luck) : (range));
148    
149     return (max (omin, min (r_max, (ran % range) + r_min)));
150     }
151    
152     return ran % range + r_min;
153     }
154    
155     /*
156     * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
157     * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
158     * Generally, op should be the player/caster/hitter requesting the roll,
159     * not the recipient (ie, the poor slob getting hit).
160     * The args are num D size (ie 4d6) [garbled 20010916]
161     */
162     int
163     die_roll (int num, int size, const object *op, int goodbad)
164     {
165 root 1.4 int min_roll, luck, total, i, gotlucky;
166 root 1.1
167     int diff = size;
168 root 1.4 min_roll = 1;
169 root 1.1 luck = total = gotlucky = 0;
170     int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
171    
172     if (size < 2 || diff < 1)
173     {
174     LOG (llevError, "Calling die_roll with num=%d size=%d\n", num, size);
175     return num; /* avoids a float exception */
176     }
177    
178     if (op->type == PLAYER)
179     luck = op->stats.luck;
180    
181     for (i = 0; i < num; i++)
182     {
183 root 1.4 if (rndm (base) < min (10, abs (luck)) && !gotlucky)
184 root 1.1 {
185     /* we have a winner */
186     gotlucky++;
187     ((luck > 0) ? (luck = 1) : (luck = -1));
188     diff -= luck;
189     if (diff < 1)
190     return (num); /*check again */
191 root 1.4 ((goodbad) ? (min_roll += luck) : (diff));
192     total += max (1, min (size, rndm (diff) + min_roll));
193 root 1.1 }
194     else
195     total += rndm (size) + 1;
196     }
197    
198     return total;
199     }
200    
201     /////////////////////////////////////////////////////////////////////////////
202    
203     #ifndef PATH_MAX
204     # define PATH_MAX 8192
205     #endif
206    
207     char *
208     path_combine (const char *src, const char *dst)
209     {
210     char *p;
211     static char path[PATH_MAX];
212    
213     if (*dst == '/')
214     {
215     /* absolute destination path => ignore source path */
216     strcpy (path, dst);
217     }
218     else
219     {
220     /* relative destination path => add after last '/' of source */
221     strcpy (path, src);
222     p = strrchr (path, '/');
223     if (p)
224     p++;
225     else
226     {
227     p = path;
228     if (*src == '/')
229     *p++ = '/';
230     }
231    
232     strcpy (p, dst);
233     }
234    
235     return path;
236     }
237    
238 root 1.2 static void
239 root 1.1 path_normalize (char *path)
240     {
241     char *p; /* points to the beginning of the path not yet processed; this is
242     either a path component or a path separator character */
243     char *q; /* points to the end of the path component p points to */
244     char *w; /* points to the end of the already normalized path; w <= p is
245     maintained */
246     size_t len; /* length of current component (which p points to) */
247    
248     p = path;
249     w = p;
250     while (*p != '\0')
251     {
252     if (*p == '/')
253     {
254     if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
255     *w++ = '/';
256    
257     p++;
258     continue;
259     }
260    
261     q = strchr (p, '/');
262     if (q == NULL)
263     q = p + strlen (p);
264     len = q - p;
265     assert (len > 0);
266    
267     if (len == 1 && *p == '.')
268     {
269     /* remove current component */
270     }
271     else if (len == 2 && memcmp (p, "..", 2) == 0)
272     {
273     if (w == path || (w == path + 3 && memcmp (path, "../", 3) == 0))
274     {
275     /* keep ".." at beginning of relative path ("../x" => "../x") */
276     memmove (w, p, len);
277     w += len;
278     }
279     else if (w == path + 1 && *path == '/')
280     {
281     /* remove ".." at beginning of absolute path ("/../x" => "/x") */
282     }
283     else
284     {
285     /* remove both current component ".." and preceding one */
286     if (w > path && w[-1] == '/')
287     w--;
288     while (w > path && w[-1] != '/')
289     w--;
290     }
291     }
292     else
293     {
294     /* normal component ==> add it */
295     memmove (w, p, len);
296     w += len;
297     }
298    
299     p = q;
300     }
301    
302     /* remove trailing slashes, but keep the one at the start of the path */
303     while (w > path + 1 && w[-1] == '/')
304     w--;
305    
306     *w = '\0';
307     }
308    
309     char *
310     path_combine_and_normalize (const char *src, const char *dst)
311     {
312     char *path;
313    
314     path = path_combine (src, dst);
315     path_normalize (path);
316     return (path);
317     }
318    
319     /**
320     * open_and_uncompress() first searches for the original filename. If it exist,
321     * then it opens it and returns the file-pointer.
322     */
323     FILE *
324     open_and_uncompress (const char *name, int flag, int *compressed)
325     {
326     *compressed = 0;
327     return fopen (name, "r");
328     }
329    
330     /*
331     * See open_and_uncompress().
332     */
333    
334     void
335     close_and_delete (FILE * fp, int compressed)
336     {
337     fclose (fp);
338     }
339    
340     /*
341     * Strip out the media tags from a String.
342     * Warning the input string will contain the result string
343     */
344     void
345     strip_media_tag (char *message)
346     {
347     int in_tag = 0;
348     char *dest;
349     char *src;
350    
351     src = dest = message;
352     while (*src != '\0')
353     {
354     if (*src == '[')
355     {
356     in_tag = 1;
357     }
358     else if (in_tag && (*src == ']'))
359     in_tag = 0;
360     else if (!in_tag)
361     {
362     *dest = *src;
363     dest++;
364     }
365     src++;
366     }
367     *dest = '\0';
368     }
369    
370     #define EOL_SIZE (sizeof("\n")-1)
371     void
372     strip_endline (char *buf)
373     {
374     if (strlen (buf) < sizeof ("\n"))
375     {
376     return;
377     }
378     if (!strcmp (buf + strlen (buf) - EOL_SIZE, "\n"))
379     buf[strlen (buf) - EOL_SIZE] = '\0';
380     }
381    
382     /**
383     * Replace in string src all occurrences of key by replacement. The resulting
384     * string is put into result; at most resultsize characters (including the
385     * terminating null character) will be written to result.
386     */
387     void
388     replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
389     {
390     size_t resultlen;
391     size_t keylen;
392    
393     /* special case to prevent infinite loop if key==replacement=="" */
394     if (strcmp (key, replacement) == 0)
395     {
396     snprintf (result, resultsize, "%s", src);
397     return;
398     }
399    
400     keylen = strlen (key);
401    
402     resultlen = 0;
403     while (*src != '\0' && resultlen + 1 < resultsize)
404     {
405     if (strncmp (src, key, keylen) == 0)
406     {
407     snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
408     resultlen += strlen (result + resultlen);
409     src += keylen;
410     }
411     else
412     {
413     result[resultlen++] = *src++;
414     }
415     }
416     result[resultlen] = '\0';
417     }
418