ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
(Generate patch)

Comparing deliantra/server/common/utils.C (file contents):
Revision 1.3 by root, Sun Sep 3 00:18:40 2006 UTC vs.
Revision 1.38 by root, Mon Jan 15 02:42:15 2007 UTC

1/*
2 * static char *rcsid_utils_c =
3 * "$Id: utils.C,v 1.3 2006/09/03 00:18:40 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
11 7
12 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by 9 it under the terms of the GNU General Public License as published by
21 17
22 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 21
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 23*/
28 24
29/* 25/*
30 * General convenience functions for crossfire. 26 * General convenience functions for crossfire.
31 */ 27 */
28
29#include <cstdlib>
30#include <sys/types.h>
31#include <unistd.h>
32#include <sys/time.h>
33#include <time.h>
34#include <signal.h>
32 35
33#include <global.h> 36#include <global.h>
34#include <funcpoint.h> 37#include <funcpoint.h>
35#include <material.h> 38#include <material.h>
39
40#include <glib.h>
36 41
37/* 42/*
38 * The random functions here take luck into account when rolling random 43 * The random functions here take luck into account when rolling random
39 * dice or numbers. This function has less of an impact the larger the 44 * dice or numbers. This function has less of an impact the larger the
40 * difference becomes in the random numbers. IE, the effect is lessened 45 * difference becomes in the random numbers. IE, the effect is lessened
48 * and if goodbad is non-zero, luck increases the roll, if zero, it decreases. 53 * and if goodbad is non-zero, luck increases the roll, if zero, it decreases.
49 * Generally, op should be the player/caster/hitter requesting the roll, 54 * Generally, op should be the player/caster/hitter requesting the roll,
50 * not the recipient (ie, the poor slob getting hit). [garbled 20010916] 55 * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
51 */ 56 */
52 57
58int
53int random_roll(int min, int max, const object *op, int goodbad) { 59random_roll (int min, int max, const object *op, int goodbad)
60{
54 int omin, diff, luck, base, ran; 61 int omin, diff, luck, base, ran;
55 62
56 omin = min; 63 omin = min;
57 diff = max - min + 1; 64 diff = max - min + 1;
58 ((diff > 2) ? (base = 20) : (base = 50)); /* d2 and d3 are corner cases */ 65 ((diff > 2) ? (base = 20) : (base = 50)); /* d2 and d3 are corner cases */
59 66
60 if (max < 1 || diff < 1) { 67 if (max < 1 || diff < 1)
68 {
61 LOG(llevError, "Calling random_roll with min=%d max=%d\n", min, max); 69 LOG (llevError, "Calling random_roll with min=%d max=%d\n", min, max);
62 return(min); /* avoids a float exception */ 70 return (min); /* avoids a float exception */
63 } 71 }
64 72
65 ran = RANDOM(); 73 ran = RANDOM ();
66 74
67 if (op->type != PLAYER) 75 if (op->type != PLAYER)
68 return((ran%diff)+min); 76 return ((ran % diff) + min);
69 77
70 luck = op->stats.luck; 78 luck = op->stats.luck;
71 if (RANDOM()%base < MIN(10, abs(luck))) { 79 if (RANDOM () % base < MIN (10, abs (luck)))
80 {
72 /* we have a winner */ 81 /* we have a winner */
73 ((luck > 0) ? (luck = 1) : (luck = -1)); 82 ((luck > 0) ? (luck = 1) : (luck = -1));
74 diff -= luck; 83 diff -= luck;
75 if (diff < 1) 84 if (diff < 1)
76 return(omin); /*check again*/ 85 return (omin); /*check again */
77 ((goodbad) ? (min += luck) : (diff)); 86 ((goodbad) ? (min += luck) : (diff));
78 87
79 return(MAX(omin, MIN(max, (ran%diff)+min))); 88 return (MAX (omin, MIN (max, (ran % diff) + min)));
80 } 89 }
81 return((ran%diff)+min); 90 return ((ran % diff) + min);
82} 91}
83 92
84/* 93/*
85 * This is a 64 bit version of random_roll above. This is needed 94 * This is a 64 bit version of random_roll above. This is needed
86 * for exp loss calculations for players changing religions. 95 * for exp loss calculations for players changing religions.
87 */ 96 */
88 97
98sint64
89sint64 random_roll64(sint64 min, sint64 max, const object *op, int goodbad) { 99random_roll64 (sint64 min, sint64 max, const object *op, int goodbad)
100{
90 sint64 omin, diff, luck, ran; 101 sint64 omin, diff, luck, ran;
91 int base; 102 int base;
92 103
93 omin = min; 104 omin = min;
94 diff = max - min + 1; 105 diff = max - min + 1;
95 ((diff > 2) ? (base = 20) : (base = 50)); /* d2 and d3 are corner cases */ 106 ((diff > 2) ? (base = 20) : (base = 50)); /* d2 and d3 are corner cases */
96 107
97 if (max < 1 || diff < 1) { 108 if (max < 1 || diff < 1)
98#ifndef WIN32 109 {
99 LOG(llevError, "Calling random_roll with min=%lld max=%lld\n", min, max);
100#else
101 LOG(llevError, "Calling random_roll with min=%I64d max=%I64d\n", min, max); 110 LOG (llevError, "Calling random_roll with min=%" PRId64 " max=%" PRId64 "\n", min, max);
102#endif
103 return(min); /* avoids a float exception */ 111 return (min); /* avoids a float exception */
104 } 112 }
105 113
106 /* Don't know of a portable call to get 64 bit random values. 114 /* Don't know of a portable call to get 64 bit random values.
107 * So make a call to get two 32 bit random numbers, and just to 115 * So make a call to get two 32 bit random numbers, and just to
108 * a little byteshifting. Do make sure the first one is only 116 * a little byteshifting. Do make sure the first one is only
109 * 32 bit, so we don't get skewed results 117 * 32 bit, so we don't get skewed results
110 */ 118 */
111 ran = (RANDOM() & 0xffffffff) | ((sint64)RANDOM() << 32); 119 ran = (RANDOM () & 0xffffffff) | ((sint64) RANDOM () << 32);
112 120
113 if (op->type != PLAYER) 121 if (op->type != PLAYER)
114 return((ran%diff)+min); 122 return ((ran % diff) + min);
115 123
116 luck = op->stats.luck; 124 luck = op->stats.luck;
117 if (RANDOM()%base < MIN(10, abs(luck))) { 125 if (RANDOM () % base < MIN (10, abs (luck)))
126 {
118 /* we have a winner */ 127 /* we have a winner */
119 ((luck > 0) ? (luck = 1) : (luck = -1)); 128 ((luck > 0) ? (luck = 1) : (luck = -1));
120 diff -= luck; 129 diff -= luck;
121 if (diff < 1) 130 if (diff < 1)
122 return(omin); /*check again*/ 131 return (omin); /*check again */
123 ((goodbad) ? (min += luck) : (diff)); 132 ((goodbad) ? (min += luck) : (diff));
124 133
125 return(MAX(omin, MIN(max, (ran%diff)+min))); 134 return (MAX (omin, MIN (max, (ran % diff) + min)));
126 } 135 }
127 return((ran%diff)+min); 136 return ((ran % diff) + min);
128} 137}
129 138
130/* 139/*
131 * Roll a number of dice (2d3, 4d6). Uses op to determine luck, 140 * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
132 * If goodbad is non-zero, luck increases the roll, if zero, it decreases. 141 * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
133 * Generally, op should be the player/caster/hitter requesting the roll, 142 * Generally, op should be the player/caster/hitter requesting the roll,
134 * not the recipient (ie, the poor slob getting hit). 143 * not the recipient (ie, the poor slob getting hit).
135 * The args are num D size (ie 4d6) [garbled 20010916] 144 * The args are num D size (ie 4d6) [garbled 20010916]
136 */ 145 */
137 146
147int
138int die_roll(int num, int size, const object *op, int goodbad) { 148die_roll (int num, int size, const object *op, int goodbad)
149{
139 int min, diff, luck, total, i, gotlucky, base, ran; 150 int min, diff, luck, total, i, gotlucky, base, ran;
140 151
141 diff = size; 152 diff = size;
142 min = 1; 153 min = 1;
143 luck = total = gotlucky = 0; 154 luck = total = gotlucky = 0;
144 ((diff > 2) ? (base = 20) : (base = 50)); /* d2 and d3 are corner cases */ 155 ((diff > 2) ? (base = 20) : (base = 50)); /* d2 and d3 are corner cases */
145 if (size < 2 || diff < 1) { 156 if (size < 2 || diff < 1)
157 {
146 LOG(llevError, "Calling die_roll with num=%d size=%d\n", num, size); 158 LOG (llevError, "Calling die_roll with num=%d size=%d\n", num, size);
147 return(num); /* avoids a float exception */ 159 return (num); /* avoids a float exception */
148 } 160 }
149 161
150 if (op->type == PLAYER) 162 if (op->type == PLAYER)
151 luck = op->stats.luck; 163 luck = op->stats.luck;
152 164
153 for (i = 0; i < num; i++) { 165 for (i = 0; i < num; i++)
166 {
154 if (RANDOM()%base < MIN(10, abs(luck)) && !gotlucky) { 167 if (RANDOM () % base < MIN (10, abs (luck)) && !gotlucky)
168 {
155 /* we have a winner */ 169 /* we have a winner */
156 gotlucky++; 170 gotlucky++;
157 ((luck > 0) ? (luck = 1) : (luck = -1)); 171 ((luck > 0) ? (luck = 1) : (luck = -1));
158 diff -= luck; 172 diff -= luck;
159 if (diff < 1) 173 if (diff < 1)
160 return(num); /*check again*/ 174 return (num); /*check again */
161 ((goodbad) ? (min += luck) : (diff)); 175 ((goodbad) ? (min += luck) : (diff));
162 ran = RANDOM(); 176 ran = RANDOM ();
163 total += MAX(1, MIN(size, (ran%diff)+min)); 177 total += MAX (1, MIN (size, (ran % diff) + min));
178 }
164 } else { 179 else
180 {
165 total += RANDOM()%size+1; 181 total += RANDOM () % size + 1;
166 } 182 }
167 } 183 }
168 return(total); 184 return (total);
169} 185}
170 186
171/* 187/*
172 * Another convenience function. Returns a number between min and max. 188 * Another convenience function. Returns a number between min and max.
173 * It is suggested one use these functions rather than RANDOM()%, as it 189 * It is suggested one use these functions rather than RANDOM()%, as it
174 * would appear that a number of off-by-one-errors exist due to improper 190 * would appear that a number of off-by-one-errors exist due to improper
175 * use of %. This should also prevent SIGFPE. 191 * use of %. This should also prevent SIGFPE.
176 */ 192 */
177 193
194int
178int rndm(int min, int max) 195rndm (int min, int max)
179{ 196{
180 int diff; 197 int diff;
181 198
182 diff = max - min + 1; 199 diff = max - min + 1;
183 if (max < 1 || diff < 1) 200 if (max < 1 || diff < 1)
184 return(min); 201 return (min);
185 202
186 return(RANDOM()%diff+min); 203 return (RANDOM () % diff + min);
187} 204}
188 205
189/* decay and destroy persihable items in a map */ 206/* decay and destroy perishable items in a map */
190 207void
191void decay_objects(mapstruct *m) 208maptile::decay_objects ()
192{ 209{
193 int x, y, destroy; 210 if (!spaces)
194 object *op, *otmp;
195
196 if (m->unique)
197 return; 211 return;
198 212
199 for (x=0; x < MAP_WIDTH(m); x++) 213 for (mapspace *ms = spaces + size (); ms-- > spaces; )
200 for (y=0; y < MAP_HEIGHT(m); y++) 214 for (object *above, *op = ms->bot; op; op = above)
201 for (op = get_map_ob(m, x, y); op; op = otmp) { 215 {
216 above = op->above;
217
202 destroy = 0; 218 bool destroy = 0;
203 otmp = op->above; 219
220 // do not decay anything above unique floor tiles (yet :)
204 if (QUERY_FLAG(op,FLAG_IS_FLOOR) && QUERY_FLAG(op, FLAG_UNIQUE)) 221 if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE))
205 break; 222 break;
223
206 if (QUERY_FLAG(op, FLAG_IS_FLOOR) || 224 if (QUERY_FLAG (op, FLAG_IS_FLOOR)
207 QUERY_FLAG(op, FLAG_OBJ_ORIGINAL) || 225 || QUERY_FLAG (op, FLAG_OBJ_ORIGINAL)
208 QUERY_FLAG(op, FLAG_OBJ_SAVE_ON_OVL) || 226 || QUERY_FLAG (op, FLAG_OBJ_SAVE_ON_OVL)
209 QUERY_FLAG(op, FLAG_UNIQUE) || 227 || QUERY_FLAG (op, FLAG_UNIQUE)
210 QUERY_FLAG(op, FLAG_OVERLAY_FLOOR) || 228 || QUERY_FLAG (op, FLAG_OVERLAY_FLOOR)
211 QUERY_FLAG(op, FLAG_UNPAID) || IS_LIVE(op)) 229 || QUERY_FLAG (op, FLAG_UNPAID)
212 continue; 230 || op->is_alive ())
213 /* otherwise, we decay and destroy */ 231 ; // do not decay
214 if (IS_WEAPON(op)) { 232 else if (op->is_weapon ())
233 {
215 op->stats.dam--; 234 op->stats.dam--;
216 if (op->stats.dam < 0) 235 if (op->stats.dam < 0)
217 destroy = 1; 236 destroy = 1;
218 } else if (IS_ARMOR(op)) {
219 op->stats.ac--;
220 if (op->stats.ac < 0)
221 destroy = 1;
222 } else if (op->type == FOOD) {
223 op->stats.food -= rndm(5,20);
224 if (op->stats.food < 0)
225 destroy = 1;
226 } else {
227 if (op->material & M_PAPER || op->material & M_LEATHER ||
228 op->material & M_WOOD || op->material & M_ORGANIC ||
229 op->material & M_CLOTH || op->material & M_LIQUID)
230 destroy = 1;
231 if (op->material & M_IRON && rndm(1,5) == 1)
232 destroy = 1;
233 if (op->material & M_GLASS && rndm(1,2) == 1)
234 destroy = 1;
235 if ((op->material & M_STONE || op->material & M_ADAMANT) &&
236 rndm(1,10) == 1)
237 destroy = 1;
238 if ((op->material & M_SOFT_METAL || op->material & M_BONE) &&
239 rndm(1,3) == 1)
240 destroy = 1;
241 if (op->material & M_ICE && MAP_TEMP(m) > 32)
242 destroy = 1;
243 }
244 /* adjust overall chance below */
245 if (destroy && rndm(0, 1)) {
246 remove_ob(op);
247 free_object(op);
248 }
249 } 237 }
238 else if (op->is_armor ())
239 {
240 op->stats.ac--;
241 if (op->stats.ac < 0)
242 destroy = 1;
243 }
244 else if (op->type == FOOD)
245 {
246 op->stats.food -= rndm (5, 20);
247 if (op->stats.food < 0)
248 destroy = 1;
249 }
250 else
251 {
252 int mat = op->material;
253
254 if (mat & M_PAPER
255 || mat & M_LEATHER
256 || mat & M_WOOD
257 || mat & M_ORGANIC
258 || mat & M_CLOTH
259 || mat & M_LIQUID
260 || (mat & M_IRON && rndm (1, 5) == 1)
261 || (mat & M_GLASS && rndm (1, 2) == 1)
262 || ((mat & M_STONE || mat & M_ADAMANT) && rndm (1, 10) == 1)
263 || ((mat & M_SOFT_METAL || mat & M_BONE) && rndm (1, 3) == 1)
264 || (mat & M_ICE && temp > 32))
265 destroy = 1;
266 }
267
268 /* adjust overall chance below */
269 if (destroy && rndm (0, 1))
270 op->destroy ();
271 }
250} 272}
251 273
252/* convert materialname to materialtype_t */ 274/* convert materialname to materialtype_t */
253 275
276materialtype_t *
254materialtype_t *name_to_material(const char *name) 277name_to_material (const char *name)
255{ 278{
256 materialtype_t *mt, *nmt; 279 materialtype_t *mt, *nmt;
257 280
258 mt = NULL; 281 mt = NULL;
259 for (nmt = materialt; nmt != NULL && nmt->next != NULL; nmt=nmt->next) { 282 for (nmt = materialt; nmt != NULL && nmt->next != NULL; nmt = nmt->next)
283 {
260 if (strcmp(name, nmt->name) == 0) { 284 if (strcmp (name, nmt->name) == 0)
285 {
261 mt = nmt; 286 mt = nmt;
262 break; 287 break;
263 } 288 }
264 } 289 }
265 return mt; 290 return mt;
266} 291}
267 292
268/* when doing transmutation of objects, we have to recheck the resistances, 293/* when doing transmutation of objects, we have to recheck the resistances,
269 * as some that did not apply previously, may apply now. 294 * as some that did not apply previously, may apply now.
270 */ 295 */
271 296
297void
272void transmute_materialname(object *op, const object *change) 298transmute_materialname (object *op, const object *change)
273{ 299{
274 materialtype_t *mt; 300 materialtype_t *mt;
275 int j; 301 int j;
276 302
277 if (op->materialname == NULL) 303 if (op->materialname == NULL)
278 return; 304 return;
279 305
280 if (change->materialname != NULL && 306 if (change->materialname != NULL && strcmp (op->materialname, change->materialname))
281 strcmp(op->materialname, change->materialname))
282 return; 307 return;
283 308
284 if (!IS_ARMOR(op)) 309 if (!op->is_armor ())
285 return; 310 return;
286 311
287 mt = name_to_material(op->materialname); 312 mt = name_to_material (op->materialname);
288 if (!mt) { 313 if (!mt)
314 {
289 LOG(llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->name, &op->name, &op->materialname); 315 LOG (llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->name, &op->name, &op->materialname);
290 return; 316 return;
291 } 317 }
292 318
293 for (j=0; j < NROFATTACKS; j++) 319 for (j = 0; j < NROFATTACKS; j++)
294 if (op->resist[j] == 0 && change->resist[j] != 0) { 320 if (op->resist[j] == 0 && change->resist[j] != 0)
321 {
295 op->resist[j] += mt->mod[j]; 322 op->resist[j] += mt->mod[j];
296 if (op->resist[j] > 100) 323 if (op->resist[j] > 100)
297 op->resist[j] = 100; 324 op->resist[j] = 100;
298 if (op->resist[j] < -100) 325 if (op->resist[j] < -100)
299 op->resist[j] = -100; 326 op->resist[j] = -100;
300 } 327 }
301} 328}
302 329
303/* set the materialname and type for an item */ 330/* set the materialname and type for an item */
331void
304void set_materialname(object *op, int difficulty, materialtype_t *nmt) 332set_materialname (object *op, int difficulty, materialtype_t *nmt)
305{ 333{
306 materialtype_t *mt, *lmt; 334 materialtype_t *mt, *lmt;
335
336#ifdef NEW_MATERIAL_CODE
307 int j; 337 int j;
338#endif
308 339
309 if (op->materialname != NULL) 340 if (op->materialname != NULL)
310 return; 341 return;
311 342
312 343
313 344
314 if (nmt == NULL) { 345 if (nmt == NULL)
346 {
315 lmt = NULL; 347 lmt = NULL;
316#ifndef NEW_MATERIAL_CODE 348#ifndef NEW_MATERIAL_CODE
317 for (mt = materialt; mt != NULL && mt->next != NULL; mt=mt->next) { 349 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
350 {
318 if (op->material & mt->material) { 351 if (op->material & mt->material)
352 {
319 lmt = mt; 353 lmt = mt;
354 break;
355 }
356 }
357
358#else
359 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
360 {
361 if (op->material & mt->material && rndm (1, 100) <= mt->chance &&
362 difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
363 {
364 lmt = mt;
365 if (!(op->is_weapon () || op->is_armor ()))
320 break; 366 break;
321 } 367 }
322 } 368 }
369#endif
370 }
371 else
372 {
373 lmt = nmt;
374 }
323 375
376 if (lmt != NULL)
377 {
378#ifndef NEW_MATERIAL_CODE
379 op->materialname = lmt->name;
380 return;
324#else 381#else
325 for (mt = materialt; mt != NULL && mt->next != NULL; mt=mt->next) { 382
326 if (op->material & mt->material && rndm(1, 100) <= mt->chance && 383 if (op->stats.dam && op->is_weapon ())
327 difficulty >= mt->difficulty &&
328 (op->magic >= mt->magic || mt->magic == 0)) {
329 lmt = mt;
330 if (!(IS_WEAPON(op) || IS_ARMOR(op)))
331 break;
332 }
333 } 384 {
334#endif
335 } else {
336 lmt = nmt;
337 }
338
339 if (lmt != NULL) {
340#ifndef NEW_MATERIAL_CODE
341 op->materialname = lmt->name;
342 return;
343#else
344
345 if (op->stats.dam && IS_WEAPON(op)) {
346 op->stats.dam += lmt->damage; 385 op->stats.dam += lmt->damage;
347 if (op->stats.dam < 1) 386 if (op->stats.dam < 1)
348 op->stats.dam = 1; 387 op->stats.dam = 1;
349 } 388 }
350 if (op->stats.sp && op->type == BOW) 389 if (op->stats.sp && op->type == BOW)
351 op->stats.sp += lmt->sp; 390 op->stats.sp += lmt->sp;
352 if (op->stats.wc && IS_WEAPON(op)) 391 if (op->stats.wc && op->is_weapon ())
353 op->stats.wc += lmt->wc; 392 op->stats.wc += lmt->wc;
354 if (IS_ARMOR(op)) { 393 if (op->is_armor ())
394 {
355 if (op->stats.ac) 395 if (op->stats.ac)
356 op->stats.ac += lmt->ac; 396 op->stats.ac += lmt->ac;
357 for (j=0; j < NROFATTACKS; j++) 397 for (j = 0; j < NROFATTACKS; j++)
358 if (op->resist[j] != 0) { 398 if (op->resist[j] != 0)
399 {
359 op->resist[j] += lmt->mod[j]; 400 op->resist[j] += lmt->mod[j];
360 if (op->resist[j] > 100) 401 if (op->resist[j] > 100)
361 op->resist[j] = 100; 402 op->resist[j] = 100;
362 if (op->resist[j] < -100) 403 if (op->resist[j] < -100)
363 op->resist[j] = -100; 404 op->resist[j] = -100;
364 } 405 }
365 } 406 }
366 op->materialname = add_string(lmt->name); 407 op->materialname = add_string (lmt->name);
367 /* dont make it unstackable if it doesn't need to be */ 408 /* dont make it unstackable if it doesn't need to be */
368 if (IS_WEAPON(op) || IS_ARMOR(op)) { 409 if (op->is_weapon () || op->is_armor ())
410 {
369 op->weight = (op->weight * lmt->weight)/100; 411 op->weight = (op->weight * lmt->weight) / 100;
370 op->value = (op->value * lmt->value)/100; 412 op->value = (op->value * lmt->value) / 100;
371 } 413 }
372#endif 414#endif
373 } 415 }
374} 416}
375 417
376/* 418/*
377 * Strip out the media tags from a String. 419 * Strip out the media tags from a String.
378 * Warning the input string will contain the result string 420 * Warning the input string will contain the result string
379 */ 421 */
422void
380void strip_media_tag(char *message){ 423strip_media_tag (char *message)
424{
381 int in_tag=0; 425 int in_tag = 0;
382 char* dest; 426 char *dest;
383 char* src; 427 char *src;
428
384 src=dest=message; 429 src = dest = message;
385 while (*src!='\0'){ 430 while (*src != '\0')
431 {
386 if (*src=='['){ 432 if (*src == '[')
433 {
387 in_tag=1; 434 in_tag = 1;
435 }
388 } else if (in_tag && (*src==']')) 436 else if (in_tag && (*src == ']'))
389 in_tag=0; 437 in_tag = 0;
390 else if (!in_tag){ 438 else if (!in_tag)
439 {
391 *dest=*src; 440 *dest = *src;
392 dest++; 441 dest++;
393 } 442 }
394 src++; 443 src++;
395 } 444 }
396 *dest='\0'; 445 *dest = '\0';
397} 446}
398 447
448const char *
399const char* strrstr(const char* haystack, const char* needle){ 449strrstr (const char *haystack, const char *needle)
450{
400 const char* lastneedle; 451 const char *lastneedle;
452
401 lastneedle=NULL; 453 lastneedle = NULL;
402 while((haystack=strstr(haystack,needle))!=NULL){ 454 while ((haystack = strstr (haystack, needle)) != NULL)
455 {
403 lastneedle=haystack; 456 lastneedle = haystack;
404 haystack++; 457 haystack++;
405 } 458 }
406 return lastneedle; 459 return lastneedle;
407 460
408} 461}
462
409#define EOL_SIZE (sizeof("\n")-1) 463#define EOL_SIZE (sizeof("\n")-1)
464void
410void strip_endline(char* buf){ 465strip_endline (char *buf)
466{
411 if (strlen(buf)<sizeof("\n")){ 467 if (strlen (buf) < sizeof ("\n"))
468 {
412 return; 469 return;
413 } 470 }
414 if (!strcmp(buf+strlen(buf)-EOL_SIZE,"\n")) 471 if (!strcmp (buf + strlen (buf) - EOL_SIZE, "\n"))
415 buf[strlen(buf)-EOL_SIZE]='\0'; 472 buf[strlen (buf) - EOL_SIZE] = '\0';
416} 473}
417 474
418/** 475/**
419 * Replace in string src all occurrences of key by replacement. The resulting 476 * Replace in string src all occurrences of key by replacement. The resulting
420 * string is put into result; at most resultsize characters (including the 477 * string is put into result; at most resultsize characters (including the
421 * terminating null character) will be written to result. 478 * terminating null character) will be written to result.
422 */ 479 */
480void
423void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize) 481replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
424{ 482{
425 size_t resultlen; 483 size_t resultlen;
426 size_t keylen; 484 size_t keylen;
427 485
428 /* special case to prevent infinite loop if key==replacement=="" */ 486 /* special case to prevent infinite loop if key==replacement=="" */
429 if(strcmp(key, replacement) == 0) 487 if (strcmp (key, replacement) == 0)
430 { 488 {
431 snprintf(result, resultsize, "%s", src); 489 snprintf (result, resultsize, "%s", src);
432 return; 490 return;
433 } 491 }
434 492
435 keylen = strlen(key); 493 keylen = strlen (key);
436 494
437 resultlen = 0; 495 resultlen = 0;
438 while(*src != '\0' && resultlen+1 < resultsize) 496 while (*src != '\0' && resultlen + 1 < resultsize)
439 { 497 {
440 if(strncmp(src, key, keylen) == 0) 498 if (strncmp (src, key, keylen) == 0)
441 { 499 {
442 snprintf(result+resultlen, resultsize-resultlen, "%s", replacement); 500 snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
443 resultlen += strlen(result+resultlen); 501 resultlen += strlen (result + resultlen);
444 src += keylen; 502 src += keylen;
445 } 503 }
446 else 504 else
447 {
448 result[resultlen++] = *src++;
449 }
450 } 505 {
506 result[resultlen++] = *src++;
507 }
508 }
451 result[resultlen] = '\0'; 509 result[resultlen] = '\0';
452} 510}
453 511
454/** 512/**
455 * Taking a string as an argument, mutate it into a string that looks like a list. 513 * Taking a string as an argument, mutate it into a string that looks like a list.
456 * a 'list' for the purposes here, is a string of items, seperated by commas, except 514 * a 'list' for the purposes here, is a string of items, seperated by commas, except
457 * for the last entry, which has an 'and' before it, and a full stop (period) after it. 515 * for the last entry, which has an 'and' before it, and a full stop (period) after it.
458 * This function will also strip all trailing non alphanumeric characters. 516 * This function will also strip all trailing non alphanumeric characters.
459 * It does not insert an oxford comma. 517 * It does not insert an oxford comma.
460 */ 518 */
461 519
520void
462void make_list_like(char *input) { 521make_list_like (char *input)
522{
463 char *p, tmp[MAX_BUF]; 523 char *p, tmp[MAX_BUF];
464 int i; 524 int i;
525
465 if (!input || strlen(input) > MAX_BUF-5) return; 526 if (!input || strlen (input) > MAX_BUF - 5)
466 /* bad stuff would happen if we continued here, the -5 is to make space for ' and ' */
467
468 strncpy(tmp, input, MAX_BUF-5);
469 /*trim all trailing commas, spaces etc.*/
470 for (i=strlen(tmp); !isalnum(tmp[i]) && i >= 0; i--)
471 tmp[i]='\0';
472 strcat(tmp, ".");
473
474 p=strrchr(tmp, ',');
475 if (p) {
476 *p='\0';
477 strcpy(input, tmp);
478 p++;
479 strcat(input, " and");
480 strcat(input, p);
481 }
482 else strcpy(input, tmp);
483 return; 527 return;
484} 528 /* bad stuff would happen if we continued here, the -5 is to make space for ' and ' */
485 529
530 strncpy (tmp, input, MAX_BUF - 5);
531 /*trim all trailing commas, spaces etc. */
532 for (i = strlen (tmp); !isalnum (tmp[i]) && i >= 0; i--)
533 tmp[i] = '\0';
534
535 strcat (tmp, ".");
536
537 p = strrchr (tmp, ',');
538 if (p)
539 {
540 *p = '\0';
541 strcpy (input, tmp);
542 p++;
543 strcat (input, " and");
544 strcat (input, p);
545 }
546 else
547 strcpy (input, tmp);
548
549 return;
550}
551
552/////////////////////////////////////////////////////////////////////////////
553
486void * 554void
487zero_initialised::operator new (size_t s) 555fork_abort (const char *msg)
488{ 556{
557 if (!fork ())
558 {
559 signal (SIGABRT, SIG_DFL);
560 abort ();
561 }
562
563 LOG (llevError, "fork abort: %s\n", msg);
564}
565
566void *salloc_ (int n) throw (std::bad_alloc)
567{
489 void *p = malloc (s); 568 void *ptr = g_slice_alloc (n);
490 569
491 memset (p, 0, s); 570 if (!ptr)
571 throw std::bad_alloc ();
572
492 return p; 573 return ptr;
493} 574}
494 575
495void 576void *salloc_ (int n, void *src) throw (std::bad_alloc)
496zero_initialised::operator delete (void *p, size_t s)
497{ 577{
498 free (p); 578 void *ptr = salloc_ (n);
499}
500 579
580 if (src)
581 memcpy (ptr, src, n);
582 else
583 memset (ptr, 0, n);
584
585 return ptr;
586}
587
588void assign (char *dst, const char *src, int maxlen)
589{
590 if (!src)
591 src = "";
592
593 int len = strlen (src);
594
595 if (len >= maxlen - 1)
596 {
597 if (maxlen <= 4)
598 {
599 memset (dst, '.', maxlen - 1);
600 dst [maxlen - 1] = 0;
601 }
602 else
603 {
604 memcpy (dst, src, maxlen - 4);
605 memcpy (dst + maxlen - 4, "...", 4);
606 }
607 }
608 else
609 memcpy (dst, src, len + 1);
610}
611
612tstamp now ()
613{
614 struct timeval tv;
615
616 gettimeofday (&tv, 0);
617 return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
618}
619
620int
621similar_direction (int a, int b)
622{
623 if (!a || !b)
624 return 0;
625
626 int diff = (b - a) & 7;
627 return diff <= 1 || diff >= 7;
628}
629

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines