Crossfire Server, Trunk  R213250
recipe.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
35 #include "global.h"
36 
37 #include <assert.h>
38 #include <ctype.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "object.h"
43 
44 static void build_stringlist(const char *str, char ***result_list, size_t *result_size);
45 static void check_formulae(void);
46 
49 
58 static recipelist *init_recipelist(void) {
59  recipelist *tl = (recipelist *)malloc(sizeof(recipelist));
60  if (tl == NULL)
62  tl->total_chance = 0;
63  tl->number = 0;
64  tl->items = NULL;
65  tl->next = NULL;
66  return tl;
67 }
68 
77 static recipe *get_empty_formula(void) {
78  // This used to be a malloc followed by setting everything to zero.
79  // So just use calloc to make it faster.
80  // SilverNexus -- 2018-10-22
81  recipe *t = (recipe *)calloc(1, sizeof(recipe));
82  if (t == NULL)
84  return t;
85 }
86 
97  recipelist *fl = formulalist;
98  int number = i;
99 
100  while (fl && number > 1) {
101  if (!(fl = fl->next))
102  break;
103  number--;
104  }
105  return fl;
106 }
107 
118 static int check_recipe(const recipe *rp) {
119  size_t i;
120  int result;
121 
122  result = 1;
123  for (i = 0; i < rp->arch_names; i++) {
124  if (find_archetype(rp->arch_name[i]) != NULL) {
125  const artifact *art = locate_recipe_artifact(rp, i);
126 
127  if (!art && strcmp(rp->title, "NONE") != 0) {
128  LOG(llevError, "\nWARNING: Formula %s of %s has no artifact.\n", rp->arch_name[i], rp->title);
129  result = 0;
130  }
131  } else {
132  LOG(llevError, "\nWARNING: Can't find archetype %s for formula %s\n", rp->arch_name[i], rp->title);
133  result = 0;
134  }
135  }
136 
137  return result;
138 }
139 
143 void init_formulae(void) {
144  static int has_been_done = 0;
145  FILE *fp;
146  char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
147  recipe *formula = NULL;
148  recipelist *fl = init_recipelist();
149  linked_char *tmp;
150  int value;
151 
152  if (!formulalist)
153  formulalist = fl;
154 
155  if (has_been_done)
156  return;
157  else
158  has_been_done = 1;
159 
160  snprintf(filename, sizeof(filename), "%s/formulae", settings.datadir);
161  LOG(llevDebug, "Reading alchemical formulae from %s...\n", filename);
162  if ((fp = fopen(filename, "r")) == NULL) {
163  LOG(llevError, "Can't open %s.\n", filename);
164  return;
165  }
166 
167  while (fgets(buf, MAX_BUF, fp) != NULL) {
168  if (*buf == '#')
169  continue;
170  if ((cp = strchr(buf, '\n')) != NULL)
171  *cp = '\0';
172  cp = buf;
173  while (*cp == ' ') /* Skip blanks */
174  cp++;
175 
176  if (!strncmp(cp, "Object", 6)) {
177  formula = get_empty_formula();
178  formula->title = add_string(strchr(cp, ' ')+1);
179  } else if (formula == NULL) {
180  LOG(llevError, "recipe.c: First key in formulae file is not \"Object\".\n");
182  } else if (!strncmp(cp, "keycode", 7)) {
183  formula->keycode = add_string(strchr(cp, ' ')+1);
184  } else if (sscanf(cp, "trans %d", &value)) {
185  formula->transmute = value;
186  } else if (sscanf(cp, "yield %d", &value)) {
187  formula->yield = value;
188  } else if (sscanf(cp, "chance %d", &value)) {
189  formula->chance = value;
190  } else if (sscanf(cp, "exp %d", &value)) {
191  formula->exp = value;
192  } else if (sscanf(cp, "diff %d", &value)) {
193  formula->diff = value;
194  } else if (!strncmp(cp, "ingred", 6)) {
195  int numb_ingred;
196  formula->ingred_count = 1;
197  cp = strchr(cp, ' ')+1;
198  do {
199  if ((next = strchr(cp, ',')) != NULL) {
200  *(next++) = '\0';
201  formula->ingred_count++;
202  }
203  tmp = (linked_char *)malloc(sizeof(linked_char));
204  /* trim the string */
205  while (*cp == ' ')
206  cp++;
207  while (*cp != '\0' && cp[strlen(cp) - 1] == ' ')
208  cp[strlen(cp) - 1] = '\0';
209  tmp->name = add_string(cp);
210  tmp->next = formula->ingred;
211  formula->ingred = tmp;
212  /* each ingredient's ASCII value is coadded. Later on this
213  * value will be used allow us to search the formula lists
214  * quickly for the right recipe.
215  */
216  formula->index += strtoint(cp);
217  } while ((cp = next) != NULL);
218  /* now find the correct (# of ingred ordered) formulalist */
219  numb_ingred = formula->ingred_count;
220  fl = formulalist;
221  while (numb_ingred != 1) {
222  if (!fl->next)
223  fl->next = init_recipelist();
224  fl = fl->next;
225  numb_ingred--;
226  }
227  fl->total_chance += formula->chance;
228  fl->number++;
229  formula->next = fl->items;
230  fl->items = formula;
231  } else if (!strncmp(cp, "arch", 4)) {
232  build_stringlist(strchr(cp, ' ')+1, &formula->arch_name, &formula->arch_names);
233  check_recipe(formula);
234  } else if (!strncmp(cp, "skill", 5)) {
235  formula->skill = add_string(strchr(cp, ' ')+1);
236  } else if (!strncmp(cp, "cauldron", 8)) {
237  formula->cauldron = add_string(strchr(cp, ' ')+1);
238  } else if (!strncmp(cp, "failure_arch ", 13)) {
239  formula->failure_arch = add_string(strchr(cp, ' ')+1);
240  } else if (!strncmp(cp, "failure_message ", 16)) {
241  formula->failure_message = add_string(strchr(cp, ' ')+1);
242  } else if (sscanf(cp, "min_level %d", &value)) {
243  formula->min_level = value;
244  } else if (!strncmp(cp, "tool ", 5)) {
245  build_stringlist(strchr(cp, ' ')+1, &formula->tool, &formula->tool_size);
246  } else if (sscanf(cp, "combination %d", &value)) {
247  formula->is_combination = value ? 1 : 0;
248  } else
249  LOG(llevError, "Unknown input in file %s: %s\n", filename, buf);
250  }
251  LOG(llevDebug, "done.\n");
252  fclose(fp);
253  /* Lastly, lets check for problems in formula we got */
254  check_formulae();
255 }
256 
271 static void check_formulae(void) {
272  recipelist *fl;
273  recipe *check, *formula;
274  int numb = 1, tool_match;
275  size_t tool_i,tool_j;
276 
277  LOG(llevDebug, "Checking formulae lists...\n");
278 
279  for (fl = formulalist; fl != NULL; fl = fl->next) {
280  for (formula = fl->items; formula != NULL; formula = formula->next)
281  for (check = formula->next; check != NULL; check = check->next)
282  /* If one recipe has a tool and another a caudron, we should be able to handle it */
283  if (check->index == formula->index &&
284  ((check->cauldron && formula->cauldron && strcmp(check->cauldron, formula->cauldron) == 0) ||
285  (check->tool_size == formula->tool_size && check->tool_size > 0))) {
286  /* Check the tool list to make sure they have no matches */
287  if (check->tool && formula->tool)
288  {
289  tool_match = 0;
290  for (tool_i = 0; tool_i < formula->tool_size; ++tool_i)
291  /* If it turns out these lists are sorted, then we could optimize this better. */
292  for (tool_j = 0; tool_j < check->tool_size; ++tool_j)
293  if (strcmp(formula->tool[tool_i], check->tool[tool_j]) == 0) {
294  tool_match = 1;
295  break; /* TODO: break out of the double loop */
296  }
297  }
298  else
299  tool_match = 1; /* If we get here, we matched on the cauldron */
300  /* Check to see if we have a denoted match */
301  if (tool_match) {
302  /* if the recipes don't have the same facility, then no issue anyway. */
303  LOG(llevError, " ERROR: On %d ingred list:\n", numb);
304  LOG(llevError, "Formulae [%s] of %s and [%s] of %s have matching index id (%d)\n",
305  formula->arch_name[0], formula->title, check->arch_name[0], check->title, formula->index);
306  }
307  }
308  numb++;
309  }
310 
311  LOG(llevDebug, "done checking.\n");
312 }
313 
321 void dump_alchemy(void) {
322  recipelist *fl = formulalist;
323  recipe *formula = NULL;
324  linked_char *next;
325  int num_ingred = 1;
326 
327  fprintf(logfile, "\n");
328  while (fl) {
329  fprintf(logfile, "\n Formulae with %d ingredient%s %d Formulae with total_chance=%d\n", num_ingred, num_ingred > 1 ? "s." : ".", fl->number, fl->total_chance);
330  for (formula = fl->items; formula != NULL; formula = formula->next) {
331  const artifact *art = NULL;
332  char buf[MAX_BUF];
333  size_t i;
334 
335  for (i = 0; i < formula->arch_names; i++) {
336  const char *string = formula->arch_name[i];
337 
338  if (find_archetype(string) != NULL) {
339  art = locate_recipe_artifact(formula, i);
340  if (!art && strcmp(formula->title, "NONE"))
341  LOG(llevError, "Formula %s has no artifact\n", formula->title);
342  else {
343  if (strcmp(formula->title, "NONE"))
344  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
345  else
346  strlcpy(buf, string, sizeof(buf));
347  fprintf(logfile, "%-30s(%d) bookchance %3d ", buf, formula->index, formula->chance);
348  fprintf(logfile, "skill %s", formula->skill);
349  fprintf(logfile, "\n");
350  if (formula->ingred != NULL) {
351  int nval = 0, tval = 0;
352  fprintf(logfile, "\tIngred: ");
353  for (next = formula->ingred; next != NULL; next = next->next) {
354  if (nval != 0)
355  fprintf(logfile, ",");
356  fprintf(logfile, "%s(%d)", next->name, (nval = strtoint(next->name)));
357  tval += nval;
358  }
359  fprintf(logfile, "\n");
360  if (tval != formula->index)
361  fprintf(logfile, "WARNING:ingredient list and formula values not equal.\n");
362  }
363  if (formula->skill != NULL)
364  fprintf(logfile, "\tSkill Required: %s", formula->skill);
365  if (formula->cauldron != NULL)
366  fprintf(logfile, "\tCauldron: %s\n", formula->cauldron);
367  fprintf(logfile, "\tDifficulty: %d\t Exp: %d\n", formula->diff, formula->exp);
368  }
369  } else
370  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
371  }
372  }
373  fprintf(logfile, "\n");
374  fl = fl->next;
375  num_ingred++;
376  }
377 }
378 
393 archetype *find_treasure_by_name(const treasure *t, const char *name, int depth) {
394  treasurelist *tl;
395  archetype *at;
396 
397  if (depth > 10)
398  return NULL;
399 
400  while (t != NULL) {
401  if (t->name != NULL) {
402  tl = find_treasurelist(t->name);
403  at = find_treasure_by_name(tl->items, name, depth+1);
404  if (at != NULL)
405  return at;
406  } else {
407  if (!strcasecmp(t->item->clone.name, name))
408  return t->item;
409  }
410  if (t->next_yes != NULL) {
411  at = find_treasure_by_name(t->next_yes, name, depth);
412  if (at != NULL)
413  return at;
414  }
415  if (t->next_no != NULL) {
416  at = find_treasure_by_name(t->next_no, name, depth);
417  if (at != NULL)
418  return at;
419  }
420  t = t->next;
421  }
422  return NULL;
423 }
424 
444 static long find_ingred_cost(const char *name) {
445  archetype *at;
446  archetype *at2;
447  const artifactlist *al;
448  const artifact *art;
449  long mult;
450  char *cp;
451  char part1[100];
452  char part2[100];
453 
454  /* same as atoi(), but skip number */
455  mult = 0;
456  while (isdigit(*name)) {
457  mult = 10*mult+(*name-'0');
458  name++;
459  }
460  if (mult > 0)
461  name++;
462  else
463  mult = 1;
464  /* first, try to match the name of an archetype */
465  for (at = first_archetype; at != NULL; at = at->next) {
466  if (at->clone.title != NULL) {
467  /* inefficient, but who cares? */
468  snprintf(part1, sizeof(part1), "%s %s", at->clone.name, at->clone.title);
469  if (!strcasecmp(part1, name))
470  return mult*at->clone.value;
471  }
472  if (!strcasecmp(at->clone.name, name))
473  return mult*at->clone.value;
474  }
475  /* second, try to match an artifact ("arch of something") */
476  cp = strstr(name, " of ");
477  if (cp != NULL) {
478  safe_strncpy(part1, name, sizeof(part1));
479  part1[cp-name] = '\0';
480  safe_strncpy(part2, cp + 4, sizeof(part2));
481  /* find the first archetype matching the first part of the name */
482  for (at = first_archetype; at != NULL; at = at->next)
483  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL)
484  break;
485  if (at != NULL) {
486  /* find the first artifact derived from that archetype (same type) */
487  for (al = first_artifactlist; al != NULL; al = al->next)
488  if (al->type == at->clone.type) {
489  for (art = al->items; art != NULL; art = art->next)
490  if (!strcasecmp(art->item->name, part2))
491  return mult*at->clone.value*art->item->value;
492  }
493  }
494  }
495  /* third, try to match a body part ("arch's something") */
496  cp = strstr(name, "'s ");
497  if (cp != NULL) {
498  safe_strncpy(part1, name, sizeof(part1));
499  part1[cp-name] = '\0';
500  safe_strncpy(part2, cp + 3, sizeof(part2));
501  /* examine all archetypes matching the first part of the name */
502  for (at = first_archetype; at != NULL; at = at->next)
503  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL) {
504  if (at->clone.randomitems != NULL) {
505  at2 = find_treasure_by_name(at->clone.randomitems->items, part2, 0);
506  if (at2 != NULL)
507  return mult*at2->clone.value*isqrt(at->clone.level*2);
508  }
509  }
510  }
511  /* failed to find any matching items -- formula should be checked */
512  return -1;
513 }
514 
523 void dump_alchemy_costs(void) {
524  recipelist *fl = formulalist;
525  recipe *formula = NULL;
526  linked_char *next;
527  int num_ingred = 1;
528  int num_errors = 0;
529  long cost;
530  long tcost;
531 
532  fprintf(logfile, "\n");
533  while (fl) {
534  fprintf(logfile, "\n Formulae with %d ingredient%s %d Formulae with total_chance=%d\n", num_ingred, num_ingred > 1 ? "s." : ".", fl->number, fl->total_chance);
535  for (formula = fl->items; formula != NULL; formula = formula->next) {
536  const artifact *art = NULL;
537  const archetype *at = NULL;
538  char buf[MAX_BUF];
539  size_t i;
540 
541  for (i = 0; i < formula->arch_names; i++) {
542  const char *string = formula->arch_name[i];
543 
544  if ((at = find_archetype(string)) != NULL) {
545  art = locate_recipe_artifact(formula, i);
546  if (!art && strcmp(formula->title, "NONE"))
547  LOG(llevError, "Formula %s has no artifact\n", formula->title);
548  else {
549  if (!strcmp(formula->title, "NONE"))
550  strlcpy(buf, string, sizeof(buf));
551  else
552  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
553  fprintf(logfile, "\n%-40s bookchance %3d skill %s\n", buf, formula->chance, formula->skill);
554  if (formula->ingred != NULL) {
555  tcost = 0;
556  for (next = formula->ingred; next != NULL; next = next->next) {
557  cost = find_ingred_cost(next->name);
558  if (cost < 0)
559  num_errors++;
560  fprintf(logfile, "\t%-33s%5ld\n", next->name, cost);
561  if (cost < 0 || tcost < 0)
562  tcost = -1;
563  else
564  tcost += cost;
565  }
566  if (art != NULL && art->item != NULL)
567  cost = at->clone.value*art->item->value;
568  else
569  cost = at->clone.value;
570  fprintf(logfile, "\t\tBuying result costs: %5ld", cost);
571  if (formula->yield > 1) {
572  fprintf(logfile, " to %ld (max %d items)\n", cost*formula->yield, formula->yield);
573  cost = cost*(formula->yield+1L)/2L;
574  } else
575  fprintf(logfile, "\n");
576  fprintf(logfile, "\t\tIngredients cost: %5ld\n\t\tComment: ", tcost);
577  if (tcost < 0)
578  fprintf(logfile, "Could not find some ingredients. Check the formula!\n");
579  else if (tcost > cost)
580  fprintf(logfile, "Ingredients are much too expensive. Useless formula.\n");
581  else if (tcost*2L > cost)
582  fprintf(logfile, "Ingredients are too expensive.\n");
583  else if (tcost*10L < cost)
584  fprintf(logfile, "Ingredients are too cheap.\n");
585  else
586  fprintf(logfile, "OK.\n");
587  }
588  }
589  } else
590  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
591  }
592  }
593  fprintf(logfile, "\n");
594  fl = fl->next;
595  num_ingred++;
596  }
597  if (num_errors > 0)
598  fprintf(logfile, "WARNING: %d objects required by the formulae do not exist in the game.\n", num_errors);
599 }
600 
609 static const char *ingred_name(const char *name) {
610  const char *cp = name;
611 
612  if (atoi(cp))
613  cp = strchr(cp, ' ')+1;
614  return cp;
615 }
616 
625 static int numb_ingred(const char *buf) {
626  int numb;
627 
628  if ((numb = atoi(buf)))
629  return numb;
630  else
631  return 1;
632 }
633 
644 int strtoint(const char *buf) {
645  const char *cp = ingred_name(buf);
646  int val = 0, len = strlen(cp), mult = numb_ingred(buf);
647 
648  while (len) {
649  val += tolower(*cp);
650  cp++; len--;
651  }
652  return val*mult;
653 }
654 
665 const artifact *locate_recipe_artifact(const recipe *rp, size_t idx) {
666  object *item = create_archetype(rp->arch_name[idx]);
667  const artifactlist *at = NULL;
668  const artifact *art = NULL;
669 
670  if (!item)
671  return (artifact *)NULL;
672 
673  if ((at = find_artifactlist(item->type)))
674  for (art = at->items; art; art = art->next)
675  if (!strcmp(art->item->name, rp->title) && legal_artifact_combination(item, art))
676  break;
677 
679 
680  return art;
681 }
682 
690  recipelist *fl = NULL;
691  int number = 0, roll = 0;
692 
693  /* first, determine # of recipelist we have */
694  for (fl = get_formulalist(1); fl; fl = fl->next)
695  number++;
696 
697  /* now, randomly choose one */
698  if (number > 0)
699  roll = RANDOM()%number;
700 
701  fl = get_formulalist(1);
702  while (roll && fl) {
703  if (fl->next)
704  fl = fl->next;
705  else
706  break;
707  roll--;
708  }
709  if (!fl) /* failed! */
710  LOG(llevError, "get_random_recipelist(): no recipelists found!\n");
711  else if (fl->total_chance == 0)
712  fl = get_random_recipelist();
713 
714  return fl;
715 }
716 
726  recipelist *fl = rpl;
727  recipe *rp = NULL;
728  int r = 0;
729 
730  /* looks like we have to choose a random one */
731  if (fl == NULL)
732  if ((fl = get_random_recipelist()) == NULL)
733  return rp;
734 
735  if (fl->total_chance > 0) {
736  r = RANDOM()%fl->total_chance;
737  for (rp = fl->items; rp; rp = rp->next) {
738  r -= rp->chance;
739  if (r < 0)
740  break;
741  }
742  }
743  return rp;
744 }
745 
749 void free_all_recipes(void) {
750  recipelist *fl, *flnext;
751  recipe *formula = NULL, *next;
752  linked_char *lchar, *charnext;
753 
754  LOG(llevDebug, "Freeing all the recipes\n");
755  for (fl = formulalist; fl != NULL; fl = flnext) {
756  flnext = fl->next;
757 
758  for (formula = fl->items; formula != NULL; formula = next) {
759  next = formula->next;
760 
761  free(formula->arch_name[0]);
762  free(formula->arch_name);
763  if (formula->title)
764  free_string(formula->title);
765  if (formula->skill)
766  free_string(formula->skill);
767  if (formula->cauldron)
768  free_string(formula->cauldron);
769  if (formula->failure_arch)
770  free_string(formula->failure_arch);
771  if (formula->failure_message)
772  free_string(formula->failure_message);
773  for (lchar = formula->ingred; lchar; lchar = charnext) {
774  charnext = lchar->next;
775  free_string(lchar->name);
776  free(lchar);
777  }
778  if (formula->tool)
779  free(formula->tool[0]);
780  free(formula->tool);
781  free(formula);
782  }
783  free(fl);
784  }
785  formulalist = NULL;
786 }
787 
799 static void build_stringlist(const char *str, char ***result_list, size_t *result_size) {
800  char *dup;
801  char *p;
802  size_t size;
803  size_t i;
804 
805  dup = strdup_local(str);
806  if (dup == NULL)
808 
809  size = 0;
810  for (p = strtok(dup, ","); p != NULL; p = strtok(NULL, ","))
811  size++;
812 
813  assert(size > 0);
814  *result_list = malloc(sizeof(**result_list) * size);
815  if (*result_list == NULL)
817  *result_size = size;
818 
819  for (i = 0; i < size; i++) {
820  (*result_list)[i] = dup;
821  dup = dup+strlen(dup)+1;
822  }
823 }
824 
832 recipe *find_recipe_for_tool(const char *tool, recipe *from) {
833  size_t t;
834  recipelist *list = from ? get_formulalist(from->ingred_count) : formulalist;
835  recipe *test = from ? from->next : list->items;
836 
837  while (list) {
838  while (test) {
839  for (t = 0; t < test->tool_size; t++) {
840  if (strcmp(test->tool[t], tool) == 0) {
841  return test;
842  }
843  }
844  test = test->next;
845  }
846 
847  list = list->next;
848  }
849 
850  return NULL;
851 }
EXTERN FILE * logfile
Definition: global.h:142
static void check_formulae(void)
Definition: recipe.c:271
archetype * find_archetype(const char *name)
Definition: arch.c:695
int diff
Definition: recipe.h:16
archetype * find_treasure_by_name(const treasure *t, const char *name, int depth)
Definition: recipe.c:393
const artifactlist * find_artifactlist(int type)
Definition: artifact.c:647
static void build_stringlist(const char *str, char ***result_list, size_t *result_size)
Definition: recipe.c:799
recipe * get_random_recipe(recipelist *rpl)
Definition: recipe.c:725
#define strdup_local
Definition: compat.h:25
struct recipeliststruct * next
Definition: recipe.h:41
static int check_recipe(const recipe *rp)
Definition: recipe.c:118
int yield
Definition: recipe.h:21
void fatal(enum fatal_error err)
Definition: utils.c:597
struct artifactstruct * items
Definition: artifact.h:30
treasurelist * find_treasurelist(const char *name)
Definition: treasure.c:290
void free_string(sstring str)
Definition: shstr.c:280
struct treasureliststruct * randomitems
Definition: object.h:387
object clone
Definition: object.h:472
linked_char * ingred
Definition: recipe.h:22
recipe * find_recipe_for_tool(const char *tool, recipe *from)
Definition: recipe.c:832
int isqrt(int n)
Definition: utils.c:586
static int numb_ingred(const char *buf)
Definition: recipe.c:625
static recipelist * init_recipelist(void)
Definition: recipe.c:58
int is_combination
Definition: recipe.h:31
int transmute
Definition: recipe.h:19
#define safe_strncpy
Definition: compat.h:23
static recipelist * get_random_recipelist(void)
Definition: recipe.c:689
Definition: object.h:467
void dump_alchemy_costs(void)
Definition: recipe.c:523
struct archt * item
Definition: treasure.h:64
void init_formulae(void)
Definition: recipe.c:143
int ingred_count
Definition: recipe.h:23
int chance
Definition: recipe.h:14
void object_free_drop_inventory(object *ob)
Definition: object.c:1389
const char * title
Definition: object.h:317
int legal_artifact_combination(const object *op, const artifact *art)
Definition: artifact.c:221
struct artifactliststruct * next
Definition: artifact.h:29
sstring title
Definition: recipe.h:11
object * create_archetype(const char *name)
Definition: arch.c:620
char ** arch_name
Definition: recipe.h:13
static const char * ingred_name(const char *name)
Definition: recipe.c:609
int total_chance
Definition: recipe.h:38
const artifact * locate_recipe_artifact(const recipe *rp, size_t idx)
Definition: recipe.c:665
#define snprintf
Definition: win32.h:46
void dump_alchemy(void)
Definition: recipe.c:321
struct linked_char * next
Definition: global.h:88
int strtoint(const char *buf)
Definition: recipe.c:644
const char * name
Definition: object.h:311
struct treasurestruct * next_no
Definition: treasure.h:68
sstring skill
Definition: recipe.h:26
EXTERN artifactlist * first_artifactlist
Definition: global.h:121
static recipelist * formulalist
Definition: recipe.c:48
int index
Definition: recipe.h:18
#define MAX_BUF
Definition: define.h:35
size_t tool_size
Definition: recipe.h:33
struct treasurestruct * items
Definition: treasure.h:90
#define tolower(C)
Definition: c_new.c:29
void free_all_recipes(void)
Definition: recipe.c:749
int exp
Definition: recipe.h:17
const char * datadir
Definition: global.h:248
const char * name
Definition: global.h:87
struct treasurestruct * next_yes
Definition: treasure.h:67
#define RANDOM()
Definition: define.h:681
size_t arch_names
Definition: recipe.h:12
uint8_t type
Definition: object.h:339
struct Settings settings
Definition: init.c:39
sstring failure_message
Definition: recipe.h:29
struct archt * next
Definition: object.h:469
struct recipestruct * next
Definition: recipe.h:24
sstring add_string(const char *str)
Definition: shstr.c:124
int strcasecmp(const char *s1, const char *s2)
Definition: porting.c:256
sstring failure_arch
Definition: recipe.h:28
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
static long find_ingred_cost(const char *name)
Definition: recipe.c:444
object * item
Definition: artifact.h:15
static recipe * get_empty_formula(void)
Definition: recipe.c:77
struct treasurestruct * next
Definition: treasure.h:66
int16_t level
Definition: object.h:352
const char * name
Definition: treasure.h:65
EXTERN archetype * first_archetype
Definition: global.h:122
int32_t value
Definition: object.h:351
sstring cauldron
Definition: recipe.h:27
char ** tool
Definition: recipe.h:32
sstring keycode
Definition: recipe.h:25
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:366
struct recipestruct * items
Definition: recipe.h:40
recipelist * get_formulalist(int i)
Definition: recipe.c:96
int min_level
Definition: recipe.h:30
struct artifactstruct * next
Definition: artifact.h:18