… | |
… | |
50 | static void build_stringlist (const char *str, char ***result_list, size_t * result_size); |
50 | static void build_stringlist (const char *str, char ***result_list, size_t * result_size); |
51 | |
51 | |
52 | static recipelist *formulalist; |
52 | static recipelist *formulalist; |
53 | |
53 | |
54 | static recipelist * |
54 | static recipelist * |
55 | init_recipelist (void) |
55 | init_recipelist () |
56 | { |
56 | { |
57 | recipelist *tl = new recipelist; |
57 | recipelist *tl = new recipelist; |
58 | |
58 | |
59 | tl->total_chance = 0; |
59 | tl->total_chance = 0; |
60 | tl->number = 0; |
60 | tl->number = 0; |
… | |
… | |
63 | |
63 | |
64 | return tl; |
64 | return tl; |
65 | } |
65 | } |
66 | |
66 | |
67 | static recipe * |
67 | static recipe * |
68 | get_empty_formula (void) |
68 | get_empty_formula () |
69 | { |
69 | { |
70 | recipe *t = new recipe; |
70 | recipe *t = new recipe; |
71 | |
71 | |
72 | t->chance = 0; |
72 | t->chance = 0; |
73 | t->index = 0; |
73 | t->index = 0; |
… | |
… | |
139 | * code, it is possible to have multiples of ingredients in a cauldron |
139 | * code, it is possible to have multiples of ingredients in a cauldron |
140 | * which could result in an index formula mismatch. We *don't* check for |
140 | * which could result in an index formula mismatch. We *don't* check for |
141 | * that possibility here. -b.t. |
141 | * that possibility here. -b.t. |
142 | */ |
142 | */ |
143 | static void |
143 | static void |
144 | check_formulae (void) |
144 | check_formulae () |
145 | { |
145 | { |
146 | recipelist *fl; |
146 | recipelist *fl; |
147 | recipe *check, *formula; |
147 | recipe *check, *formula; |
148 | int numb = 1; |
148 | int numb = 1; |
149 | |
149 | |
… | |
… | |
169 | /* |
169 | /* |
170 | * init_formulae() - Builds up the lists of formula from the file in |
170 | * init_formulae() - Builds up the lists of formula from the file in |
171 | * the libdir. -b.t. |
171 | * the libdir. -b.t. |
172 | */ |
172 | */ |
173 | void |
173 | void |
174 | init_formulae (void) |
174 | init_formulae () |
175 | { |
175 | { |
176 | static int has_been_done = 0; |
176 | static int has_been_done = 0; |
177 | FILE *fp; |
177 | FILE *fp; |
178 | char filename[MAX_BUF], buf[MAX_BUF], *cp, *next; |
178 | char filename[MAX_BUF], buf[MAX_BUF], *cp, *next; |
179 | recipe *formula = NULL; |
179 | recipe *formula = NULL; |
… | |
… | |
321 | } |
321 | } |
322 | |
322 | |
323 | return 0; |
323 | return 0; |
324 | } |
324 | } |
325 | |
325 | |
326 | /* If several archetypes have the same name, the value of the first |
|
|
327 | * one with that name will be returned. This happens for the |
|
|
328 | * mushrooms (mushroom_1, mushroom_2 and mushroom_3). For the |
|
|
329 | * monsters' body parts, there may be several monsters with the same |
|
|
330 | * name. This is not a problem if these monsters have the same level |
|
|
331 | * (e.g. sage & c_sage) or if only one of the monsters generates the |
|
|
332 | * body parts that we are looking for (e.g. big_dragon and |
|
|
333 | * big_dragon_worthless). */ |
|
|
334 | static long |
|
|
335 | find_ingred_cost (const char *name) |
|
|
336 | { |
|
|
337 | archetype *at2; |
|
|
338 | artifactlist *al; |
|
|
339 | artifact *art; |
|
|
340 | long mult; |
|
|
341 | char *cp; |
|
|
342 | char part1[100]; |
|
|
343 | char part2[100]; |
|
|
344 | |
|
|
345 | /* same as atoi(), but skip number */ |
|
|
346 | mult = 0; |
|
|
347 | while (isdigit (*name)) |
|
|
348 | { |
|
|
349 | mult = 10 * mult + (*name - '0'); |
|
|
350 | name++; |
|
|
351 | } |
|
|
352 | |
|
|
353 | if (mult > 0) |
|
|
354 | name++; |
|
|
355 | else |
|
|
356 | mult = 1; |
|
|
357 | |
|
|
358 | /* first, try to match the name of an archetype */ |
|
|
359 | for_all_archetypes (at) |
|
|
360 | { |
|
|
361 | if (at->title != NULL) |
|
|
362 | { |
|
|
363 | /* inefficient, but who cares? */ |
|
|
364 | sprintf (part1, "%s %s", &at->object::name, &at->title); |
|
|
365 | if (!strcasecmp (part1, name)) |
|
|
366 | return mult * at->value; |
|
|
367 | } |
|
|
368 | if (!strcasecmp (at->object::name, name)) |
|
|
369 | return mult * at->value; |
|
|
370 | } |
|
|
371 | |
|
|
372 | /* second, try to match an artifact ("arch of something") */ |
|
|
373 | cp = strstr (name, " of "); |
|
|
374 | if (cp != NULL) |
|
|
375 | { |
|
|
376 | strcpy (part1, name); |
|
|
377 | part1[cp - name] = '\0'; |
|
|
378 | strcpy (part2, cp + 4); |
|
|
379 | |
|
|
380 | /* find the first archetype matching the first part of the name */ |
|
|
381 | for_all_archetypes (at) |
|
|
382 | if (at->object::name.eq_nc (part1) && !at->title) |
|
|
383 | { |
|
|
384 | /* find the first artifact derived from that archetype (same type) */ |
|
|
385 | for (al = first_artifactlist; al; al = al->next) |
|
|
386 | if (al->type == at->type) |
|
|
387 | { |
|
|
388 | for (art = al->items; art; art = art->next) |
|
|
389 | if (!strcasecmp (art->item->name, part2)) |
|
|
390 | return mult * at->value * art->item->value; |
|
|
391 | } |
|
|
392 | } |
|
|
393 | } |
|
|
394 | |
|
|
395 | /* third, try to match a body part ("arch's something") */ |
|
|
396 | cp = strstr (name, "'s "); |
|
|
397 | if (cp) |
|
|
398 | { |
|
|
399 | strcpy (part1, name); |
|
|
400 | part1[cp - name] = '\0'; |
|
|
401 | strcpy (part2, cp + 3); |
|
|
402 | /* examine all archetypes matching the first part of the name */ |
|
|
403 | for_all_archetypes (at) |
|
|
404 | if (at->object::name.eq_nc (part1) && !at->title) |
|
|
405 | { |
|
|
406 | if (at->randomitems) |
|
|
407 | { |
|
|
408 | at2 = find_treasure_by_name (at->randomitems->items, part2, 0); |
|
|
409 | if (at2) |
|
|
410 | return mult * at2->value * isqrt (at->level * 2); |
|
|
411 | } |
|
|
412 | } |
|
|
413 | } |
|
|
414 | |
|
|
415 | /* failed to find any matching items -- formula should be checked */ |
|
|
416 | return -1; |
|
|
417 | } |
|
|
418 | |
|
|
419 | static const char * |
326 | static const char * |
420 | ingred_name (const char *name) |
327 | ingred_name (const char *name) |
421 | { |
328 | { |
422 | const char *cp = name; |
329 | const char *cp = name; |
423 | |
330 | |
… | |
… | |
472 | |
379 | |
473 | return 0; |
380 | return 0; |
474 | } |
381 | } |
475 | |
382 | |
476 | static recipelist * |
383 | static recipelist * |
477 | get_random_recipelist (void) |
384 | get_random_recipelist () |
478 | { |
385 | { |
479 | recipelist *fl = NULL; |
386 | recipelist *fl = NULL; |
480 | int number = 0, roll = 0; |
387 | int number = 0, roll = 0; |
481 | |
388 | |
482 | /* first, determine # of recipelist we have */ |
389 | /* first, determine # of recipelist we have */ |
… | |
… | |
525 | if (r < 0) |
432 | if (r < 0) |
526 | break; |
433 | break; |
527 | } |
434 | } |
528 | } |
435 | } |
529 | return rp; |
436 | return rp; |
530 | } |
|
|
531 | |
|
|
532 | static void |
|
|
533 | free_all_recipes (void) |
|
|
534 | { |
|
|
535 | recipelist *fl = formulalist, *flnext; |
|
|
536 | recipe *formula = NULL, *next; |
|
|
537 | linked_char *lchar, *charnext; |
|
|
538 | |
|
|
539 | LOG (llevDebug, "Freeing all the recipes\n"); |
|
|
540 | for (fl = formulalist; fl != NULL; fl = flnext) |
|
|
541 | { |
|
|
542 | flnext = fl->next; |
|
|
543 | |
|
|
544 | for (formula = fl->items; formula != NULL; formula = next) |
|
|
545 | { |
|
|
546 | next = formula->next; |
|
|
547 | |
|
|
548 | free (formula->arch_name[0]); |
|
|
549 | free (formula->arch_name); |
|
|
550 | |
|
|
551 | for (lchar = formula->ingred; lchar; lchar = charnext) |
|
|
552 | { |
|
|
553 | charnext = lchar->next; |
|
|
554 | delete lchar; |
|
|
555 | } |
|
|
556 | delete formula; |
|
|
557 | } |
|
|
558 | |
|
|
559 | delete fl; |
|
|
560 | } |
|
|
561 | } |
437 | } |
562 | |
438 | |
563 | /** |
439 | /** |
564 | * Split a comma separated string list into words. |
440 | * Split a comma separated string list into words. |
565 | * |
441 | * |