ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.19
Committed: Sat Nov 17 23:40:00 2018 UTC (5 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +1 -0 lines
Log Message:
copyright update 2018

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.19 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
5 root 1.17 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
6 root 1.5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
7     * Copyright (©) 1992 Frank Tore Johansen
8 root 1.16 *
9 root 1.1 * Deliantra is free software: you can redistribute it and/or modify it under
10     * the terms of the Affero GNU General Public License as published by the
11     * Free Software Foundation, either version 3 of the License, or (at your
12     * option) any later version.
13 root 1.16 *
14 root 1.1 * This program is distributed in the hope that it will be useful,
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     * GNU General Public License for more details.
18 root 1.16 *
19 root 1.1 * You should have received a copy of the Affero GNU General Public License
20     * and the GNU General Public License along with this program. If not, see
21     * <http://www.gnu.org/licenses/>.
22 root 1.16 *
23 root 1.1 * The authors can be reached via e-mail to <support@deliantra.net>
24     */
25    
26     /*
27     * compatibility functions for older (GPL) source code parts
28     */
29    
30     #include <cstring>
31     #include <assert.h>
32     #include <stdio.h>
33     #include <string.h>
34     #include <limits.h>
35    
36     #include <global.h>
37     #include "define.h"
38     #include "path.h"
39    
40 root 1.18 /* buf_overflow() - we don't want to exceed the buffer size of
41 root 1.1 * 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     * The random functions here take luck into account when rolling random
64     * dice or numbers. This function has less of an impact the larger the
65     * difference becomes in the random numbers. IE, the effect is lessened
66     * on a 1-1000 roll, vs a 1-6 roll. This can be used by crafty programmers,
67     * to specifically disable luck in certain rolls, simply by making the
68     * numbers larger (ie, 1d1000 > 500 vs 1d6 > 3)
69     */
70    
71     /*
72     * Roll a random number between min and max. Uses op to determine luck,
73     * and if goodbad is non-zero, luck increases the roll, if zero, it decreases.
74     * Generally, op should be the player/caster/hitter requesting the roll,
75     * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
76     */
77     int
78 root 1.11 random_roll (int r_min, int r_max, const object *op, bool prefer_high)
79 root 1.1 {
80 root 1.13 if (r_min > r_max)
81     swap (r_min, r_max);
82 root 1.1
83 root 1.13 int range = r_max - r_min + 1;
84     int num = rndm (r_min, r_max);
85 root 1.1
86 root 1.13 if (op->stats.luck)
87 root 1.1 {
88 root 1.13 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
89 root 1.1
90 root 1.13 if (rndm (base) < min (10, abs (op->stats.luck)))
91 root 1.1 {
92 root 1.13 // we have a winner, increase/decrease number by one accordingly
93     int adjust = sign (op->stats.luck);
94    
95     if (!prefer_high)
96     adjust = -adjust;
97    
98     num = clamp (num + adjust, r_min, r_max);
99 root 1.1 }
100     }
101    
102 root 1.13 return num;
103 root 1.1 }
104    
105     /*
106     * This is a 64 bit version of random_roll above. This is needed
107     * for exp loss calculations for players changing religions.
108     */
109     sint64
110 root 1.11 random_roll64 (sint64 r_min, sint64 r_max, const object *op, bool prefer_high)
111 root 1.1 {
112 root 1.13 if (r_min > r_max)
113     swap (r_min, r_max);
114 root 1.1
115 root 1.13 sint64 range = r_max - r_min + 1;
116 root 1.18 /*
117 root 1.10 * Make a call to get two 32 bit unsigned random numbers, and just do
118 root 1.1 * a little bitshifting.
119     */
120 root 1.13 sint64 num = rndm.next () ^ (sint64 (rndm.next ()) << 31);
121    
122     num = num % range + r_min;
123 root 1.1
124 root 1.10 if (op->stats.luck)
125     {
126 root 1.13 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
127 root 1.1
128 root 1.13 if (rndm (base) < min (10, abs (op->stats.luck)))
129 root 1.10 {
130 root 1.13 // we have a winner, increase/decrease number by one accordingly
131     int adjust = sign (op->stats.luck);
132    
133     if (!prefer_high)
134     adjust = -adjust;
135 root 1.10
136 root 1.13 num = clamp (num + adjust, r_min, r_max);
137 root 1.10 }
138 root 1.1 }
139    
140 root 1.13 return num;
141 root 1.1 }
142    
143     /*
144     * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
145     * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
146     * Generally, op should be the player/caster/hitter requesting the roll,
147     * not the recipient (ie, the poor slob getting hit).
148     * The args are num D size (ie 4d6) [garbled 20010916]
149     */
150     int
151 root 1.11 die_roll (int num, int size, const object *op, bool prefer_high)
152 root 1.1 {
153 root 1.4 int min_roll, luck, total, i, gotlucky;
154 root 1.1
155     int diff = size;
156 root 1.4 min_roll = 1;
157 root 1.1 luck = total = gotlucky = 0;
158     int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
159    
160     if (size < 2 || diff < 1)
161     {
162 root 1.12 LOG (llevError | logBacktrace, "Calling die_roll with num=%d size=%d\n", num, size);
163 root 1.1 return num; /* avoids a float exception */
164     }
165    
166     if (op->type == PLAYER)
167     luck = op->stats.luck;
168    
169     for (i = 0; i < num; i++)
170     {
171 root 1.4 if (rndm (base) < min (10, abs (luck)) && !gotlucky)
172 root 1.1 {
173     /* we have a winner */
174     gotlucky++;
175     ((luck > 0) ? (luck = 1) : (luck = -1));
176     diff -= luck;
177     if (diff < 1)
178     return (num); /*check again */
179 root 1.11 ((prefer_high) ? (min_roll += luck) : (diff));
180 root 1.4 total += max (1, min (size, rndm (diff) + min_roll));
181 root 1.1 }
182     else
183     total += rndm (size) + 1;
184     }
185    
186     return total;
187     }
188    
189     /////////////////////////////////////////////////////////////////////////////
190    
191     #ifndef PATH_MAX
192     # define PATH_MAX 8192
193     #endif
194    
195     char *
196     path_combine (const char *src, const char *dst)
197     {
198     char *p;
199     static char path[PATH_MAX];
200    
201     if (*dst == '/')
202     {
203     /* absolute destination path => ignore source path */
204     strcpy (path, dst);
205     }
206     else
207     {
208     /* relative destination path => add after last '/' of source */
209     strcpy (path, src);
210     p = strrchr (path, '/');
211     if (p)
212     p++;
213     else
214     {
215     p = path;
216     if (*src == '/')
217     *p++ = '/';
218     }
219    
220     strcpy (p, dst);
221     }
222    
223     return path;
224     }
225    
226 root 1.2 static void
227 root 1.1 path_normalize (char *path)
228     {
229     char *p; /* points to the beginning of the path not yet processed; this is
230     either a path component or a path separator character */
231     char *q; /* points to the end of the path component p points to */
232     char *w; /* points to the end of the already normalized path; w <= p is
233     maintained */
234     size_t len; /* length of current component (which p points to) */
235    
236     p = path;
237     w = p;
238     while (*p != '\0')
239     {
240     if (*p == '/')
241     {
242     if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
243     *w++ = '/';
244    
245     p++;
246     continue;
247     }
248    
249     q = strchr (p, '/');
250     if (q == NULL)
251     q = p + strlen (p);
252     len = q - p;
253     assert (len > 0);
254    
255     if (len == 1 && *p == '.')
256     {
257     /* remove current component */
258     }
259     else if (len == 2 && memcmp (p, "..", 2) == 0)
260     {
261     if (w == path || (w == path + 3 && memcmp (path, "../", 3) == 0))
262     {
263     /* keep ".." at beginning of relative path ("../x" => "../x") */
264     memmove (w, p, len);
265     w += len;
266     }
267     else if (w == path + 1 && *path == '/')
268     {
269     /* remove ".." at beginning of absolute path ("/../x" => "/x") */
270     }
271     else
272     {
273     /* remove both current component ".." and preceding one */
274     if (w > path && w[-1] == '/')
275     w--;
276     while (w > path && w[-1] != '/')
277     w--;
278     }
279     }
280     else
281     {
282     /* normal component ==> add it */
283     memmove (w, p, len);
284     w += len;
285     }
286    
287     p = q;
288     }
289    
290     /* remove trailing slashes, but keep the one at the start of the path */
291     while (w > path + 1 && w[-1] == '/')
292     w--;
293    
294     *w = '\0';
295     }
296    
297     char *
298     path_combine_and_normalize (const char *src, const char *dst)
299     {
300     char *path;
301    
302     path = path_combine (src, dst);
303     path_normalize (path);
304     return (path);
305     }
306    
307     #define EOL_SIZE (sizeof("\n")-1)
308     void
309     strip_endline (char *buf)
310     {
311 root 1.9 if (*buf && buf [strlen (buf) - 1] == '\n')
312     buf [strlen (buf) - 1] = '\0';
313 root 1.1 }
314    
315     /**
316     * Replace in string src all occurrences of key by replacement. The resulting
317     * string is put into result; at most resultsize characters (including the
318     * terminating null character) will be written to result.
319     */
320     void
321     replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
322     {
323     size_t resultlen;
324     size_t keylen;
325    
326     /* special case to prevent infinite loop if key==replacement=="" */
327     if (strcmp (key, replacement) == 0)
328     {
329     snprintf (result, resultsize, "%s", src);
330     return;
331     }
332    
333     keylen = strlen (key);
334    
335     resultlen = 0;
336     while (*src != '\0' && resultlen + 1 < resultsize)
337     {
338     if (strncmp (src, key, keylen) == 0)
339     {
340     snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
341     resultlen += strlen (result + resultlen);
342     src += keylen;
343     }
344     else
345     {
346     result[resultlen++] = *src++;
347     }
348     }
349     result[resultlen] = '\0';
350     }
351