ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.17
Committed: Wed Nov 16 23:41:59 2016 UTC (7 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.16: +1 -1 lines
Log Message:
copyright update 2016

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen
7 *
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 /* 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 random_roll (int r_min, int r_max, const object *op, bool prefer_high)
78 {
79 if (r_min > r_max)
80 swap (r_min, r_max);
81
82 int range = r_max - r_min + 1;
83 int num = rndm (r_min, r_max);
84
85 if (op->stats.luck)
86 {
87 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
88
89 if (rndm (base) < min (10, abs (op->stats.luck)))
90 {
91 // 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 }
99 }
100
101 return num;
102 }
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 random_roll64 (sint64 r_min, sint64 r_max, const object *op, bool prefer_high)
110 {
111 if (r_min > r_max)
112 swap (r_min, r_max);
113
114 sint64 range = r_max - r_min + 1;
115 /*
116 * Make a call to get two 32 bit unsigned random numbers, and just do
117 * a little bitshifting.
118 */
119 sint64 num = rndm.next () ^ (sint64 (rndm.next ()) << 31);
120
121 num = num % range + r_min;
122
123 if (op->stats.luck)
124 {
125 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
126
127 if (rndm (base) < min (10, abs (op->stats.luck)))
128 {
129 // 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
135 num = clamp (num + adjust, r_min, r_max);
136 }
137 }
138
139 return num;
140 }
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 die_roll (int num, int size, const object *op, bool prefer_high)
151 {
152 int min_roll, luck, total, i, gotlucky;
153
154 int diff = size;
155 min_roll = 1;
156 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 LOG (llevError | logBacktrace, "Calling die_roll with num=%d size=%d\n", num, size);
162 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 if (rndm (base) < min (10, abs (luck)) && !gotlucky)
171 {
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 ((prefer_high) ? (min_roll += luck) : (diff));
179 total += max (1, min (size, rndm (diff) + min_roll));
180 }
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 static void
226 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 if (*buf && buf [strlen (buf) - 1] == '\n')
311 buf [strlen (buf) - 1] = '\0';
312 }
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