ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.8
Committed: Sun Apr 4 04:59:20 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +1 -7 lines
Log Message:
*** empty log message ***

File Contents

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