ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.10
Committed: Thu Apr 29 15:49:04 2010 UTC (14 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.9: +16 -14 lines
Log Message:
indent

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 root 1.10 * Make a call to get two 32 bit unsigned random numbers, and just do
124 root 1.1 * a little bitshifting.
125     */
126     sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31);
127    
128 root 1.10 if (op->stats.luck)
129     {
130     int luck = op->stats.luck;
131 root 1.1
132 root 1.10 if (rndm (base) < min (10, abs (luck)))
133     {
134     /* we have a winner */
135     luck = luck > 0 ? 1 : -1;
136    
137     range -= luck;
138     if (range < 1)
139     return omin; /*check again */
140 root 1.1
141 root 1.10 if (goodbad)
142     r_min += luck;
143 root 1.1
144 root 1.10 return (max (omin, min (r_max, (ran % range) + r_min)));
145     }
146 root 1.1 }
147    
148     return ran % range + r_min;
149     }
150    
151     /*
152     * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
153     * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
154     * Generally, op should be the player/caster/hitter requesting the roll,
155     * not the recipient (ie, the poor slob getting hit).
156     * The args are num D size (ie 4d6) [garbled 20010916]
157     */
158     int
159     die_roll (int num, int size, const object *op, int goodbad)
160     {
161 root 1.4 int min_roll, luck, total, i, gotlucky;
162 root 1.1
163     int diff = size;
164 root 1.4 min_roll = 1;
165 root 1.1 luck = total = gotlucky = 0;
166     int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
167    
168     if (size < 2 || diff < 1)
169     {
170     LOG (llevError, "Calling die_roll with num=%d size=%d\n", num, size);
171     return num; /* avoids a float exception */
172     }
173    
174     if (op->type == PLAYER)
175     luck = op->stats.luck;
176    
177     for (i = 0; i < num; i++)
178     {
179 root 1.4 if (rndm (base) < min (10, abs (luck)) && !gotlucky)
180 root 1.1 {
181     /* we have a winner */
182     gotlucky++;
183     ((luck > 0) ? (luck = 1) : (luck = -1));
184     diff -= luck;
185     if (diff < 1)
186     return (num); /*check again */
187 root 1.4 ((goodbad) ? (min_roll += luck) : (diff));
188     total += max (1, min (size, rndm (diff) + min_roll));
189 root 1.1 }
190     else
191     total += rndm (size) + 1;
192     }
193    
194     return total;
195     }
196    
197     /////////////////////////////////////////////////////////////////////////////
198    
199     #ifndef PATH_MAX
200     # define PATH_MAX 8192
201     #endif
202    
203     char *
204     path_combine (const char *src, const char *dst)
205     {
206     char *p;
207     static char path[PATH_MAX];
208    
209     if (*dst == '/')
210     {
211     /* absolute destination path => ignore source path */
212     strcpy (path, dst);
213     }
214     else
215     {
216     /* relative destination path => add after last '/' of source */
217     strcpy (path, src);
218     p = strrchr (path, '/');
219     if (p)
220     p++;
221     else
222     {
223     p = path;
224     if (*src == '/')
225     *p++ = '/';
226     }
227    
228     strcpy (p, dst);
229     }
230    
231     return path;
232     }
233    
234 root 1.2 static void
235 root 1.1 path_normalize (char *path)
236     {
237     char *p; /* points to the beginning of the path not yet processed; this is
238     either a path component or a path separator character */
239     char *q; /* points to the end of the path component p points to */
240     char *w; /* points to the end of the already normalized path; w <= p is
241     maintained */
242     size_t len; /* length of current component (which p points to) */
243    
244     p = path;
245     w = p;
246     while (*p != '\0')
247     {
248     if (*p == '/')
249     {
250     if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
251     *w++ = '/';
252    
253     p++;
254     continue;
255     }
256    
257     q = strchr (p, '/');
258     if (q == NULL)
259     q = p + strlen (p);
260     len = q - p;
261     assert (len > 0);
262    
263     if (len == 1 && *p == '.')
264     {
265     /* remove current component */
266     }
267     else if (len == 2 && memcmp (p, "..", 2) == 0)
268     {
269     if (w == path || (w == path + 3 && memcmp (path, "../", 3) == 0))
270     {
271     /* keep ".." at beginning of relative path ("../x" => "../x") */
272     memmove (w, p, len);
273     w += len;
274     }
275     else if (w == path + 1 && *path == '/')
276     {
277     /* remove ".." at beginning of absolute path ("/../x" => "/x") */
278     }
279     else
280     {
281     /* remove both current component ".." and preceding one */
282     if (w > path && w[-1] == '/')
283     w--;
284     while (w > path && w[-1] != '/')
285     w--;
286     }
287     }
288     else
289     {
290     /* normal component ==> add it */
291     memmove (w, p, len);
292     w += len;
293     }
294    
295     p = q;
296     }
297    
298     /* remove trailing slashes, but keep the one at the start of the path */
299     while (w > path + 1 && w[-1] == '/')
300     w--;
301    
302     *w = '\0';
303     }
304    
305     char *
306     path_combine_and_normalize (const char *src, const char *dst)
307     {
308     char *path;
309    
310     path = path_combine (src, dst);
311     path_normalize (path);
312     return (path);
313     }
314    
315     #define EOL_SIZE (sizeof("\n")-1)
316     void
317     strip_endline (char *buf)
318     {
319 root 1.9 if (*buf && buf [strlen (buf) - 1] == '\n')
320     buf [strlen (buf) - 1] = '\0';
321 root 1.1 }
322    
323     /**
324     * Replace in string src all occurrences of key by replacement. The resulting
325     * string is put into result; at most resultsize characters (including the
326     * terminating null character) will be written to result.
327     */
328     void
329     replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
330     {
331     size_t resultlen;
332     size_t keylen;
333    
334     /* special case to prevent infinite loop if key==replacement=="" */
335     if (strcmp (key, replacement) == 0)
336     {
337     snprintf (result, resultsize, "%s", src);
338     return;
339     }
340    
341     keylen = strlen (key);
342    
343     resultlen = 0;
344     while (*src != '\0' && resultlen + 1 < resultsize)
345     {
346     if (strncmp (src, key, keylen) == 0)
347     {
348     snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
349     resultlen += strlen (result + resultlen);
350     src += keylen;
351     }
352     else
353     {
354     result[resultlen++] = *src++;
355     }
356     }
357     result[resultlen] = '\0';
358     }
359