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, 5 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

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