ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/compat.C
Revision: 1.8
Committed: Sun Apr 4 04:59:20 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +1 -7 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 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
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 //TODO: only one caller left
67 void
68 fatal (const char *msg)
69 {
70 LOG (llevError, "FATAL: %s\n", msg);
71 cleanup (msg, 1);
72 }
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 * Make a call to get two 32 bit unsigned random numbers, and just to
124 * a little bitshifting.
125 */
126 sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31);
127
128 if (op->type != PLAYER)
129 return ((ran % range) + r_min);
130
131 int luck = op->stats.luck;
132
133 if (rndm (base) < min (10, abs (luck)))
134 {
135 /* we have a winner */
136 ((luck > 0) ? (luck = 1) : (luck = -1));
137 range -= luck;
138 if (range < 1)
139 return (omin); /*check again */
140
141 ((goodbad) ? (r_min += luck) : (range));
142
143 return (max (omin, min (r_max, (ran % range) + r_min)));
144 }
145
146 return ran % range + r_min;
147 }
148
149 /*
150 * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
151 * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
152 * Generally, op should be the player/caster/hitter requesting the roll,
153 * not the recipient (ie, the poor slob getting hit).
154 * The args are num D size (ie 4d6) [garbled 20010916]
155 */
156 int
157 die_roll (int num, int size, const object *op, int goodbad)
158 {
159 int min_roll, luck, total, i, gotlucky;
160
161 int diff = size;
162 min_roll = 1;
163 luck = total = gotlucky = 0;
164 int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
165
166 if (size < 2 || diff < 1)
167 {
168 LOG (llevError, "Calling die_roll with num=%d size=%d\n", num, size);
169 return num; /* avoids a float exception */
170 }
171
172 if (op->type == PLAYER)
173 luck = op->stats.luck;
174
175 for (i = 0; i < num; i++)
176 {
177 if (rndm (base) < min (10, abs (luck)) && !gotlucky)
178 {
179 /* we have a winner */
180 gotlucky++;
181 ((luck > 0) ? (luck = 1) : (luck = -1));
182 diff -= luck;
183 if (diff < 1)
184 return (num); /*check again */
185 ((goodbad) ? (min_roll += luck) : (diff));
186 total += max (1, min (size, rndm (diff) + min_roll));
187 }
188 else
189 total += rndm (size) + 1;
190 }
191
192 return total;
193 }
194
195 /////////////////////////////////////////////////////////////////////////////
196
197 #ifndef PATH_MAX
198 # define PATH_MAX 8192
199 #endif
200
201 char *
202 path_combine (const char *src, const char *dst)
203 {
204 char *p;
205 static char path[PATH_MAX];
206
207 if (*dst == '/')
208 {
209 /* absolute destination path => ignore source path */
210 strcpy (path, dst);
211 }
212 else
213 {
214 /* relative destination path => add after last '/' of source */
215 strcpy (path, src);
216 p = strrchr (path, '/');
217 if (p)
218 p++;
219 else
220 {
221 p = path;
222 if (*src == '/')
223 *p++ = '/';
224 }
225
226 strcpy (p, dst);
227 }
228
229 return path;
230 }
231
232 static void
233 path_normalize (char *path)
234 {
235 char *p; /* points to the beginning of the path not yet processed; this is
236 either a path component or a path separator character */
237 char *q; /* points to the end of the path component p points to */
238 char *w; /* points to the end of the already normalized path; w <= p is
239 maintained */
240 size_t len; /* length of current component (which p points to) */
241
242 p = path;
243 w = p;
244 while (*p != '\0')
245 {
246 if (*p == '/')
247 {
248 if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
249 *w++ = '/';
250
251 p++;
252 continue;
253 }
254
255 q = strchr (p, '/');
256 if (q == NULL)
257 q = p + strlen (p);
258 len = q - p;
259 assert (len > 0);
260
261 if (len == 1 && *p == '.')
262 {
263 /* remove current component */
264 }
265 else if (len == 2 && memcmp (p, "..", 2) == 0)
266 {
267 if (w == path || (w == path + 3 && memcmp (path, "../", 3) == 0))
268 {
269 /* keep ".." at beginning of relative path ("../x" => "../x") */
270 memmove (w, p, len);
271 w += len;
272 }
273 else if (w == path + 1 && *path == '/')
274 {
275 /* remove ".." at beginning of absolute path ("/../x" => "/x") */
276 }
277 else
278 {
279 /* remove both current component ".." and preceding one */
280 if (w > path && w[-1] == '/')
281 w--;
282 while (w > path && w[-1] != '/')
283 w--;
284 }
285 }
286 else
287 {
288 /* normal component ==> add it */
289 memmove (w, p, len);
290 w += len;
291 }
292
293 p = q;
294 }
295
296 /* remove trailing slashes, but keep the one at the start of the path */
297 while (w > path + 1 && w[-1] == '/')
298 w--;
299
300 *w = '\0';
301 }
302
303 char *
304 path_combine_and_normalize (const char *src, const char *dst)
305 {
306 char *path;
307
308 path = path_combine (src, dst);
309 path_normalize (path);
310 return (path);
311 }
312
313 /**
314 * open_and_uncompress() first searches for the original filename. If it exist,
315 * then it opens it and returns the file-pointer.
316 */
317 FILE *
318 open_and_uncompress (const char *name, int flag, int *compressed)
319 {
320 *compressed = 0;
321 return fopen (name, "r");
322 }
323
324 /*
325 * See open_and_uncompress().
326 */
327
328 void
329 close_and_delete (FILE * fp, int compressed)
330 {
331 fclose (fp);
332 }
333
334 /*
335 * Strip out the media tags from a String.
336 * Warning the input string will contain the result string
337 */
338 void
339 strip_media_tag (char *message)
340 {
341 int in_tag = 0;
342 char *dest;
343 char *src;
344
345 src = dest = message;
346 while (*src != '\0')
347 {
348 if (*src == '[')
349 {
350 in_tag = 1;
351 }
352 else if (in_tag && (*src == ']'))
353 in_tag = 0;
354 else if (!in_tag)
355 {
356 *dest = *src;
357 dest++;
358 }
359 src++;
360 }
361 *dest = '\0';
362 }
363
364 #define EOL_SIZE (sizeof("\n")-1)
365 void
366 strip_endline (char *buf)
367 {
368 if (strlen (buf) < sizeof ("\n"))
369 {
370 return;
371 }
372 if (!strcmp (buf + strlen (buf) - EOL_SIZE, "\n"))
373 buf[strlen (buf) - EOL_SIZE] = '\0';
374 }
375
376 /**
377 * Replace in string src all occurrences of key by replacement. The resulting
378 * string is put into result; at most resultsize characters (including the
379 * terminating null character) will be written to result.
380 */
381 void
382 replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
383 {
384 size_t resultlen;
385 size_t keylen;
386
387 /* special case to prevent infinite loop if key==replacement=="" */
388 if (strcmp (key, replacement) == 0)
389 {
390 snprintf (result, resultsize, "%s", src);
391 return;
392 }
393
394 keylen = strlen (key);
395
396 resultlen = 0;
397 while (*src != '\0' && resultlen + 1 < resultsize)
398 {
399 if (strncmp (src, key, keylen) == 0)
400 {
401 snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
402 resultlen += strlen (result + resultlen);
403 src += keylen;
404 }
405 else
406 {
407 result[resultlen++] = *src++;
408 }
409 }
410 result[resultlen] = '\0';
411 }
412