00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00041 #include <stdlib.h>
00042 #include <global.h>
00043
00051 int random_roll(int min, int max, const object *op, int goodbad) {
00052 int omin, diff, luck, base, ran;
00053
00054 omin = min;
00055 diff = max-min+1;
00056 ((diff > 2) ? (base = 20) : (base = 50));
00057
00058 if (max < 1 || diff < 1) {
00059 LOG(llevError, "Calling random_roll with min=%d max=%d\n", min, max);
00060 return(min);
00061 }
00062
00063 ran = RANDOM();
00064
00065 if (op->type != PLAYER)
00066 return((ran%diff)+min);
00067
00068 luck = op->stats.luck;
00069 if (RANDOM()%base < MIN(10, abs(luck))) {
00070
00071 ((luck > 0) ? (luck = 1) : (luck = -1));
00072 diff -= luck;
00073 if (diff < 1)
00074 return(omin);
00075 ((goodbad) ? (min += luck) : (diff));
00076
00077 return(MAX(omin, MIN(max, (ran%diff)+min)));
00078 }
00079 return((ran%diff)+min);
00080 }
00081
00086 sint64 random_roll64(sint64 min, sint64 max, const object *op, int goodbad) {
00087 sint64 omin, diff, luck, ran;
00088 int base;
00089
00090 omin = min;
00091 diff = max-min+1;
00092 ((diff > 2) ? (base = 20) : (base = 50));
00093
00094 if (max < 1 || diff < 1) {
00095 #ifndef WIN32
00096 LOG(llevError, "Calling random_roll with min=%lld max=%lld\n", min, max);
00097 #else
00098 LOG(llevError, "Calling random_roll with min=%I64d max=%I64d\n", min, max);
00099 #endif
00100 return(min);
00101 }
00102
00103
00104
00105
00106
00107
00108 ran = (RANDOM()&0xffffffff)|((sint64)RANDOM()<<32);
00109
00110 if (op->type != PLAYER)
00111 return((ran%diff)+min);
00112
00113 luck = op->stats.luck;
00114 if (RANDOM()%base < MIN(10, abs(luck))) {
00115
00116 ((luck > 0) ? (luck = 1) : (luck = -1));
00117 diff -= luck;
00118 if (diff < 1)
00119 return (omin);
00120 ((goodbad) ? (min += luck) : (diff));
00121
00122 return (MAX(omin, MIN(max, (ran%diff)+min)));
00123 }
00124 return ((ran%diff)+min);
00125 }
00126
00134 int die_roll(int num, int size, const object *op, int goodbad) {
00135 int min, diff, luck, total, i, gotlucky, base, ran;
00136
00137 diff = size;
00138 min = 1;
00139 luck = total = gotlucky = 0;
00140 ((diff > 2) ? (base = 20) : (base = 50));
00141 if (size < 2 || diff < 1) {
00142 LOG(llevError, "Calling die_roll with num=%d size=%d\n", num, size);
00143 return(num);
00144 }
00145
00146 if (op->type == PLAYER)
00147 luck = op->stats.luck;
00148
00149 for (i = 0; i < num; i++) {
00150 if (RANDOM()%base < MIN(10, abs(luck)) && !gotlucky) {
00151
00152 gotlucky++;
00153 ((luck > 0) ? (luck = 1) : (luck = -1));
00154 diff -= luck;
00155 if (diff < 1)
00156 return(num);
00157 ((goodbad) ? (min += luck) : (diff));
00158 ran = RANDOM();
00159 total += MAX(1, MIN(size, (ran%diff)+min));
00160 } else {
00161 total += RANDOM()%size+1;
00162 }
00163 }
00164 return(total);
00165 }
00166
00174 int rndm(int min, int max) {
00175 int diff;
00176
00177 diff = max-min+1;
00178 if (max < 1 || diff < 1)
00179 return (min);
00180
00181 return (RANDOM()%diff+min);
00182 }
00183
00187 void decay_objects(mapstruct *m) {
00188 int x, y, destroy;
00189 object *op, *otmp;
00190
00191 if (m->unique)
00192 return;
00193
00194 for (x = 0; x < MAP_WIDTH(m); x++)
00195 for (y = 0; y < MAP_HEIGHT(m); y++)
00196 for (op = GET_MAP_OB(m, x, y); op; op = otmp) {
00197 destroy = 0;
00198 otmp = op->above;
00199 if (QUERY_FLAG(op, FLAG_IS_FLOOR) && QUERY_FLAG(op, FLAG_UNIQUE))
00200 break;
00201 if (QUERY_FLAG(op, FLAG_IS_FLOOR)
00202 || QUERY_FLAG(op, FLAG_OBJ_ORIGINAL)
00203 || QUERY_FLAG(op, FLAG_UNIQUE)
00204 || QUERY_FLAG(op, FLAG_OVERLAY_FLOOR)
00205 || QUERY_FLAG(op, FLAG_UNPAID)
00206 || IS_LIVE(op))
00207 continue;
00208 if (op->head)
00209
00210 continue;
00211
00212 if (IS_WEAPON(op)) {
00213 op->stats.dam--;
00214 if (op->stats.dam < 0)
00215 destroy = 1;
00216 } else if (IS_ARMOR(op)
00217 || IS_SHIELD(op)
00218 || op->type == GIRDLE
00219 || op->type == GLOVES
00220 || op->type == CLOAK) {
00221 op->stats.ac--;
00222 if (op->stats.ac < 0)
00223 destroy = 1;
00224 } else if (op->type == FOOD) {
00225 op->stats.food -= rndm(5, 20);
00226 if (op->stats.food < 0)
00227 destroy = 1;
00228 } else {
00229 if (op->material&M_PAPER
00230 || op->material&M_LEATHER
00231 || op->material&M_WOOD
00232 || op->material&M_ORGANIC
00233 || op->material&M_CLOTH
00234 || op->material&M_LIQUID)
00235 destroy = 1;
00236 if (op->material&M_IRON && rndm(1, 5) == 1)
00237 destroy = 1;
00238 if (op->material&M_GLASS && rndm(1, 2) == 1)
00239 destroy = 1;
00240 if ((op->material&M_STONE || op->material&M_ADAMANT) && rndm(1, 10) == 1)
00241 destroy = 1;
00242 if ((op->material&M_SOFT_METAL || op->material&M_BONE)
00243 && rndm(1, 3) == 1)
00244 destroy = 1;
00245 if (op->material&M_ICE && rndm(0, 100) > 70)
00246 destroy = 1;
00247 }
00248
00249 if (destroy && rndm(0, 1)) {
00250 remove_ob(op);
00251 free_object(op);
00252 }
00253 }
00254 }
00255
00262 materialtype_t *name_to_material(const char *name) {
00263 materialtype_t *mt, *nmt;
00264
00265 mt = NULL;
00266 for (nmt = materialt; nmt != NULL && nmt->next != NULL; nmt = nmt->next) {
00267 if (strcmp(name, nmt->name) == 0) {
00268 mt = nmt;
00269 break;
00270 }
00271 }
00272 return mt;
00273 }
00274
00281 void transmute_materialname(object *op, const object *change) {
00282 materialtype_t *mt;
00283 int j;
00284
00285 if (op->materialname == NULL)
00286 return;
00287
00288 if (change->materialname != NULL
00289 && strcmp(op->materialname, change->materialname))
00290 return;
00291
00292 if (!(IS_ARMOR(op) || IS_SHIELD(op) || op->type == GIRDLE || op->type == GLOVES || op->type == CLOAK))
00293 return;
00294
00295 mt = name_to_material(op->materialname);
00296 if (!mt) {
00297 LOG(llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", op->arch->name, op->name, op->materialname);
00298 return;
00299 }
00300
00301 for (j = 0; j < NROFATTACKS; j++)
00302 if (op->resist[j] == 0 && change->resist[j] != 0) {
00303 op->resist[j] += mt->mod[j];
00304 if (op->resist[j] > 100)
00305 op->resist[j] = 100;
00306 if (op->resist[j] < -100)
00307 op->resist[j] = -100;
00308 }
00309 }
00310
00314 void set_materialname(object *op, int difficulty, materialtype_t *nmt) {
00315 materialtype_t *mt, *lmt;
00316
00317 if (op->materialname != NULL)
00318 return;
00319
00320 if (nmt == NULL) {
00321 lmt = NULL;
00322 #ifndef NEW_MATERIAL_CODE
00323 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next) {
00324 if (op->material&mt->material) {
00325 lmt = mt;
00326 break;
00327 }
00328 }
00329 #else
00330 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next) {
00331 if (op->material&mt->material
00332 && rndm(1, 100) <= mt->chance
00333 && difficulty >= mt->difficulty
00334 && (op->magic >= mt->magic || mt->magic == 0)) {
00335 lmt = mt;
00336 if (!(IS_WEAPON(op) || IS_ARMOR(op) || IS_SHIELD(op) || op->type == GIRDLE || op->type == GLOVES || op->type == CLOAK))
00337 break;
00338 }
00339 }
00340 #endif
00341 } else {
00342 lmt = nmt;
00343 }
00344
00345 if (lmt != NULL) {
00346 #ifndef NEW_MATERIAL_CODE
00347 op->materialname = add_string(lmt->name);
00348 return;
00349 #else
00350
00351 if (op->stats.dam && IS_WEAPON(op)) {
00352 op->stats.dam += lmt->damage;
00353 if (op->stats.dam < 1)
00354 op->stats.dam = 1;
00355 }
00356 if (op->stats.sp && op->type == BOW)
00357 op->stats.sp += lmt->sp;
00358 if (op->stats.wc && IS_WEAPON(op))
00359 op->stats.wc += lmt->wc;
00360 if (IS_ARMOR(op) || IS_SHIELD(op) || op->type == GIRDLE || op->type == GLOVES || op->type == CLOAK) {
00361 int j;
00362
00363 if (op->stats.ac)
00364 op->stats.ac += lmt->ac;
00365 for (j = 0; j < NROFATTACKS; j++)
00366 if (op->resist[j] != 0) {
00367 op->resist[j] += lmt->mod[j];
00368 if (op->resist[j] > 100)
00369 op->resist[j] = 100;
00370 if (op->resist[j] < -100)
00371 op->resist[j] = -100;
00372 }
00373 }
00374 op->materialname = add_string(lmt->name);
00375
00376 if (IS_WEAPON(op) || IS_ARMOR(op) || IS_SHIELD(op) || op->type == GIRDLE || op->type == GLOVES || op->type == CLOAK) {
00377 op->weight = (op->weight*lmt->weight)/100;
00378 op->value = (op->value*lmt->value)/100;
00379 }
00380 #endif
00381 }
00382 }
00383
00388 void strip_media_tag(char *message) {
00389 int in_tag = 0;
00390 char *dest;
00391 char *src;
00392 src = dest = message;
00393
00394 while (*src != '\0') {
00395 if (*src == '[') {
00396 in_tag = 1;
00397 } else if (in_tag && (*src == ']'))
00398 in_tag = 0;
00399 else if (!in_tag) {
00400 *dest = *src;
00401 dest++;
00402 }
00403 src++;
00404 }
00405 *dest = '\0';
00406 }
00407
00414 const char *strrstr(const char *haystack, const char *needle) {
00415 const char *lastneedle;
00416
00417 lastneedle = NULL;
00418 while ((haystack = strstr(haystack, needle)) != NULL) {
00419 lastneedle = haystack;
00420 haystack++;
00421 }
00422 return lastneedle;
00423
00424 }
00425
00426 #define EOL_SIZE (sizeof("\n")-1)
00427
00431 void strip_endline(char *buf) {
00432 if (strlen(buf) < sizeof("\n")) {
00433 return;
00434 }
00435 if (!strcmp(buf+strlen(buf)-EOL_SIZE, "\n"))
00436 buf[strlen(buf)-EOL_SIZE] = '\0';
00437 }
00438
00444 void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize) {
00445 size_t resultlen;
00446 size_t keylen;
00447
00448
00449 if (strcmp(key, replacement) == 0) {
00450 snprintf(result, resultsize, "%s", src);
00451 return;
00452 }
00453
00454 keylen = strlen(key);
00455
00456 resultlen = 0;
00457 while (*src != '\0' && resultlen+1 < resultsize) {
00458 if (strncmp(src, key, keylen) == 0) {
00459 snprintf(result+resultlen, resultsize-resultlen, "%s", replacement);
00460 resultlen += strlen(result+resultlen);
00461 src += keylen;
00462 } else {
00463 result[resultlen++] = *src++;
00464 }
00465 }
00466 result[resultlen] = '\0';
00467 }
00468
00485 void make_list_like(char *input) {
00486 char *p, tmp[MAX_BUF];
00487 int i;
00488 if (!input || strlen(input) > MAX_BUF-5)
00489 return;
00490
00491
00492 strncpy(tmp, input, MAX_BUF-5);
00493
00494 for (i = strlen(tmp); !isalnum(tmp[i]) && i >= 0; i--)
00495 tmp[i] = '\0';
00496 strcat(tmp, ".");
00497
00498 p = strrchr(tmp, ',');
00499 if (p) {
00500 *p = '\0';
00501 strcpy(input, tmp);
00502 p++;
00503 strcat(input, " and");
00504 strcat(input, p);
00505 } else
00506 strcpy(input, tmp);
00507 return;
00508 }
00509
00516 void replace_unprintable_chars(char *buf) {
00517 char *p;
00518
00519 for (p = buf; *p != '\0'; p++) {
00520 if (*p < ' ') {
00521 *p = ' ';
00522 }
00523 }
00524 }