ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.16
Committed: Mon Oct 29 23:55:52 2012 UTC (11 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_1
Changes since 1.15: +5 -5 lines
Log Message:
trailing space removal

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.16 *
4 root 1.15 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 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.16 *
8 root 1.1 * 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 root 1.16 *
13 root 1.1 * 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 root 1.16 *
18 root 1.1 * 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.16 *
22 root 1.1 * 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     /* buf_overflow() - we don't want to exceed the buffer size of
40     * buf1 by adding on buf2! Returns true if overflow will occur.
41     */
42     int
43     buf_overflow (const char *buf1, const char *buf2, int bufsize)
44     {
45     int len1 = 0, len2 = 0;
46    
47     if (buf1)
48     len1 = strlen (buf1);
49    
50     if (buf2)
51     len2 = strlen (buf2);
52    
53     if ((len1 + len2) >= bufsize)
54     return 1;
55    
56     return 0;
57     }
58    
59     /////////////////////////////////////////////////////////////////////////////
60    
61     /*
62     * The random functions here take luck into account when rolling random
63     * dice or numbers. This function has less of an impact the larger the
64     * difference becomes in the random numbers. IE, the effect is lessened
65     * on a 1-1000 roll, vs a 1-6 roll. This can be used by crafty programmers,
66     * to specifically disable luck in certain rolls, simply by making the
67     * numbers larger (ie, 1d1000 > 500 vs 1d6 > 3)
68     */
69    
70     /*
71     * Roll a random number between min and max. Uses op to determine luck,
72     * and if goodbad is non-zero, luck increases the roll, if zero, it decreases.
73     * Generally, op should be the player/caster/hitter requesting the roll,
74     * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
75     */
76     int
77 root 1.11 random_roll (int r_min, int r_max, const object *op, bool prefer_high)
78 root 1.1 {
79 root 1.13 if (r_min > r_max)
80     swap (r_min, r_max);
81 root 1.1
82 root 1.13 int range = r_max - r_min + 1;
83     int num = rndm (r_min, r_max);
84 root 1.1
85 root 1.13 if (op->stats.luck)
86 root 1.1 {
87 root 1.13 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
88 root 1.1
89 root 1.13 if (rndm (base) < min (10, abs (op->stats.luck)))
90 root 1.1 {
91 root 1.13 // we have a winner, increase/decrease number by one accordingly
92     int adjust = sign (op->stats.luck);
93    
94     if (!prefer_high)
95     adjust = -adjust;
96    
97     num = clamp (num + adjust, r_min, r_max);
98 root 1.1 }
99     }
100    
101 root 1.13 return num;
102 root 1.1 }
103    
104     /*
105     * This is a 64 bit version of random_roll above. This is needed
106     * for exp loss calculations for players changing religions.
107     */
108     sint64
109 root 1.11 random_roll64 (sint64 r_min, sint64 r_max, const object *op, bool prefer_high)
110 root 1.1 {
111 root 1.13 if (r_min > r_max)
112     swap (r_min, r_max);
113 root 1.1
114 root 1.13 sint64 range = r_max - r_min + 1;
115 root 1.1 /*
116 root 1.10 * Make a call to get two 32 bit unsigned random numbers, and just do
117 root 1.1 * a little bitshifting.
118     */
119 root 1.13 sint64 num = rndm.next () ^ (sint64 (rndm.next ()) << 31);
120    
121     num = num % range + r_min;
122 root 1.1
123 root 1.10 if (op->stats.luck)
124     {
125 root 1.13 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
126 root 1.1
127 root 1.13 if (rndm (base) < min (10, abs (op->stats.luck)))
128 root 1.10 {
129 root 1.13 // we have a winner, increase/decrease number by one accordingly
130     int adjust = sign (op->stats.luck);
131    
132     if (!prefer_high)
133     adjust = -adjust;
134 root 1.10
135 root 1.13 num = clamp (num + adjust, r_min, r_max);
136 root 1.10 }
137 root 1.1 }
138    
139 root 1.13 return num;
140 root 1.1 }
141    
142     /*
143     * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
144     * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
145     * Generally, op should be the player/caster/hitter requesting the roll,
146     * not the recipient (ie, the poor slob getting hit).
147     * The args are num D size (ie 4d6) [garbled 20010916]
148     */
149     int
150 root 1.11 die_roll (int num, int size, const object *op, bool prefer_high)
151 root 1.1 {
152 root 1.4 int min_roll, luck, total, i, gotlucky;
153 root 1.1
154     int diff = size;
155 root 1.4 min_roll = 1;
156 root 1.1 luck = total = gotlucky = 0;
157     int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
158    
159     if (size < 2 || diff < 1)
160     {
161 root 1.12 LOG (llevError | logBacktrace, "Calling die_roll with num=%d size=%d\n", num, size);
162 root 1.1 return num; /* avoids a float exception */
163     }
164    
165     if (op->type == PLAYER)
166     luck = op->stats.luck;
167    
168     for (i = 0; i < num; i++)
169     {
170 root 1.4 if (rndm (base) < min (10, abs (luck)) && !gotlucky)
171 root 1.1 {
172     /* we have a winner */
173     gotlucky++;
174     ((luck > 0) ? (luck = 1) : (luck = -1));
175     diff -= luck;
176     if (diff < 1)
177     return (num); /*check again */
178 root 1.11 ((prefer_high) ? (min_roll += luck) : (diff));
179 root 1.4 total += max (1, min (size, rndm (diff) + min_roll));
180 root 1.1 }
181     else
182     total += rndm (size) + 1;
183     }
184    
185     return total;
186     }
187    
188     /////////////////////////////////////////////////////////////////////////////
189    
190     #ifndef PATH_MAX
191     # define PATH_MAX 8192
192     #endif
193    
194     char *
195     path_combine (const char *src, const char *dst)
196     {
197     char *p;
198     static char path[PATH_MAX];
199    
200     if (*dst == '/')
201     {
202     /* absolute destination path => ignore source path */
203     strcpy (path, dst);
204     }
205     else
206     {
207     /* relative destination path => add after last '/' of source */
208     strcpy (path, src);
209     p = strrchr (path, '/');
210     if (p)
211     p++;
212     else
213     {
214     p = path;
215     if (*src == '/')
216     *p++ = '/';
217     }
218    
219     strcpy (p, dst);
220     }
221    
222     return path;
223     }
224    
225 root 1.2 static void
226 root 1.1 path_normalize (char *path)
227     {
228     char *p; /* points to the beginning of the path not yet processed; this is
229     either a path component or a path separator character */
230     char *q; /* points to the end of the path component p points to */
231     char *w; /* points to the end of the already normalized path; w <= p is
232     maintained */
233     size_t len; /* length of current component (which p points to) */
234    
235     p = path;
236     w = p;
237     while (*p != '\0')
238     {
239     if (*p == '/')
240     {
241     if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
242     *w++ = '/';
243    
244     p++;
245     continue;
246     }
247    
248     q = strchr (p, '/');
249     if (q == NULL)
250     q = p + strlen (p);
251     len = q - p;
252     assert (len > 0);
253    
254     if (len == 1 && *p == '.')
255     {
256     /* remove current component */
257     }
258     else if (len == 2 && memcmp (p, "..", 2) == 0)
259     {
260     if (w == path || (w == path + 3 && memcmp (path, "../", 3) == 0))
261     {
262     /* keep ".." at beginning of relative path ("../x" => "../x") */
263     memmove (w, p, len);
264     w += len;
265     }
266     else if (w == path + 1 && *path == '/')
267     {
268     /* remove ".." at beginning of absolute path ("/../x" => "/x") */
269     }
270     else
271     {
272     /* remove both current component ".." and preceding one */
273     if (w > path && w[-1] == '/')
274     w--;
275     while (w > path && w[-1] != '/')
276     w--;
277     }
278     }
279     else
280     {
281     /* normal component ==> add it */
282     memmove (w, p, len);
283     w += len;
284     }
285    
286     p = q;
287     }
288    
289     /* remove trailing slashes, but keep the one at the start of the path */
290     while (w > path + 1 && w[-1] == '/')
291     w--;
292    
293     *w = '\0';
294     }
295    
296     char *
297     path_combine_and_normalize (const char *src, const char *dst)
298     {
299     char *path;
300    
301     path = path_combine (src, dst);
302     path_normalize (path);
303     return (path);
304     }
305    
306     #define EOL_SIZE (sizeof("\n")-1)
307     void
308     strip_endline (char *buf)
309     {
310 root 1.9 if (*buf && buf [strlen (buf) - 1] == '\n')
311     buf [strlen (buf) - 1] = '\0';
312 root 1.1 }
313    
314     /**
315     * Replace in string src all occurrences of key by replacement. The resulting
316     * string is put into result; at most resultsize characters (including the
317     * terminating null character) will be written to result.
318     */
319     void
320     replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
321     {
322     size_t resultlen;
323     size_t keylen;
324    
325     /* special case to prevent infinite loop if key==replacement=="" */
326     if (strcmp (key, replacement) == 0)
327     {
328     snprintf (result, resultsize, "%s", src);
329     return;
330     }
331    
332     keylen = strlen (key);
333    
334     resultlen = 0;
335     while (*src != '\0' && resultlen + 1 < resultsize)
336     {
337     if (strncmp (src, key, keylen) == 0)
338     {
339     snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
340     resultlen += strlen (result + resultlen);
341     src += keylen;
342     }
343     else
344     {
345     result[resultlen++] = *src++;
346     }
347     }
348     result[resultlen] = '\0';
349     }
350