Crossfire Server, Trunk  R20513
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  recipe *t = (recipe *)malloc(sizeof(recipe));
79  if (t == NULL)
81  t->chance = 0;
82  t->index = 0;
83  t->transmute = 0;
84  t->yield = 0;
85  t->diff = 0;
86  t->exp = 0;
87  t->keycode = NULL;
88  t->title = NULL;
89  t->arch_names = 0;
90  t->arch_name = NULL;
91  t->skill = NULL;
92  t->cauldron = NULL;
93  t->ingred = NULL;
94  t->ingred_count = 0;
95  t->next = NULL;
96  t->failure_arch = NULL;
97  t->failure_message = NULL;
98  t->min_level = 0;
99  t->is_combination = 0;
100  t->tool = NULL;
101  t->tool_size = 0;
102  return t;
103 }
104 
115  recipelist *fl = formulalist;
116  int number = i;
117 
118  while (fl && number > 1) {
119  if (!(fl = fl->next))
120  break;
121  number--;
122  }
123  return fl;
124 }
125 
136 static int check_recipe(const recipe *rp) {
137  size_t i;
138  int result;
139 
140  result = 1;
141  for (i = 0; i < rp->arch_names; i++) {
142  if (find_archetype(rp->arch_name[i]) != NULL) {
143  const artifact *art = locate_recipe_artifact(rp, i);
144 
145  if (!art && strcmp(rp->title, "NONE") != 0) {
146  LOG(llevError, "\nWARNING: Formula %s of %s has no artifact.\n", rp->arch_name[i], rp->title);
147  result = 0;
148  }
149  } else {
150  LOG(llevError, "\nWARNING: Can't find archetype %s for formula %s\n", rp->arch_name[i], rp->title);
151  result = 0;
152  }
153  }
154 
155  return result;
156 }
157 
161 void init_formulae(void) {
162  static int has_been_done = 0;
163  FILE *fp;
164  char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
165  recipe *formula = NULL;
166  recipelist *fl = init_recipelist();
167  linked_char *tmp;
168  int value;
169 
170  if (!formulalist)
171  formulalist = fl;
172 
173  if (has_been_done)
174  return;
175  else
176  has_been_done = 1;
177 
178  snprintf(filename, sizeof(filename), "%s/formulae", settings.datadir);
179  LOG(llevDebug, "Reading alchemical formulae from %s...\n", filename);
180  if ((fp = fopen(filename, "r")) == NULL) {
181  LOG(llevError, "Can't open %s.\n", filename);
182  return;
183  }
184 
185  while (fgets(buf, MAX_BUF, fp) != NULL) {
186  if (*buf == '#')
187  continue;
188  if ((cp = strchr(buf, '\n')) != NULL)
189  *cp = '\0';
190  cp = buf;
191  while (*cp == ' ') /* Skip blanks */
192  cp++;
193 
194  if (!strncmp(cp, "Object", 6)) {
195  formula = get_empty_formula();
196  formula->title = add_string(strchr(cp, ' ')+1);
197  } else if (formula == NULL) {
198  LOG(llevError, "recipe.c: First key in formulae file is not \"Object\".\n");
200  } else if (!strncmp(cp, "keycode", 7)) {
201  formula->keycode = add_string(strchr(cp, ' ')+1);
202  } else if (sscanf(cp, "trans %d", &value)) {
203  formula->transmute = value;
204  } else if (sscanf(cp, "yield %d", &value)) {
205  formula->yield = value;
206  } else if (sscanf(cp, "chance %d", &value)) {
207  formula->chance = value;
208  } else if (sscanf(cp, "exp %d", &value)) {
209  formula->exp = value;
210  } else if (sscanf(cp, "diff %d", &value)) {
211  formula->diff = value;
212  } else if (!strncmp(cp, "ingred", 6)) {
213  int numb_ingred;
214  formula->ingred_count = 1;
215  cp = strchr(cp, ' ')+1;
216  do {
217  if ((next = strchr(cp, ',')) != NULL) {
218  *(next++) = '\0';
219  formula->ingred_count++;
220  }
221  tmp = (linked_char *)malloc(sizeof(linked_char));
222  /* trim the string */
223  while (*cp == ' ')
224  cp++;
225  while (cp != '\0' && cp[strlen(cp) - 1] == ' ')
226  cp[strlen(cp) - 1] = '\0';
227  tmp->name = add_string(cp);
228  tmp->next = formula->ingred;
229  formula->ingred = tmp;
230  /* each ingredient's ASCII value is coadded. Later on this
231  * value will be used allow us to search the formula lists
232  * quickly for the right recipe.
233  */
234  formula->index += strtoint(cp);
235  } while ((cp = next) != NULL);
236  /* now find the correct (# of ingred ordered) formulalist */
237  numb_ingred = formula->ingred_count;
238  fl = formulalist;
239  while (numb_ingred != 1) {
240  if (!fl->next)
241  fl->next = init_recipelist();
242  fl = fl->next;
243  numb_ingred--;
244  }
245  fl->total_chance += formula->chance;
246  fl->number++;
247  formula->next = fl->items;
248  fl->items = formula;
249  } else if (!strncmp(cp, "arch", 4)) {
250  build_stringlist(strchr(cp, ' ')+1, &formula->arch_name, &formula->arch_names);
251  check_recipe(formula);
252  } else if (!strncmp(cp, "skill", 5)) {
253  formula->skill = add_string(strchr(cp, ' ')+1);
254  } else if (!strncmp(cp, "cauldron", 8)) {
255  formula->cauldron = add_string(strchr(cp, ' ')+1);
256  } else if (!strncmp(cp, "failure_arch ", 13)) {
257  formula->failure_arch = add_string(strchr(cp, ' ')+1);
258  } else if (!strncmp(cp, "failure_message ", 16)) {
259  formula->failure_message = add_string(strchr(cp, ' ')+1);
260  } else if (sscanf(cp, "min_level %d", &value)) {
261  formula->min_level = value;
262  } else if (!strncmp(cp, "tool ", 5)) {
263  build_stringlist(strchr(cp, ' ')+1, &formula->tool, &formula->tool_size);
264  } else if (sscanf(cp, "combination %d", &value)) {
265  formula->is_combination = value ? 1 : 0;
266  } else
267  LOG(llevError, "Unknown input in file %s: %s\n", filename, buf);
268  }
269  LOG(llevDebug, "done.\n");
270  fclose(fp);
271  /* Lastly, lets check for problems in formula we got */
272  check_formulae();
273 }
274 
289 static void check_formulae(void) {
290  recipelist *fl;
291  recipe *check, *formula;
292  int numb = 1;
293 
294  LOG(llevDebug, "Checking formulae lists...\n");
295 
296  for (fl = formulalist; fl != NULL; fl = fl->next) {
297  for (formula = fl->items; formula != NULL; formula = formula->next)
298  for (check = formula->next; check != NULL; check = check->next)
299  if (check->index == formula->index && strcmp(check->cauldron, formula->cauldron) == 0) {
300  /* if the recipes don't have the same facility, then no issue anyway. */
301  LOG(llevError, " ERROR: On %d ingred list:\n", numb);
302  LOG(llevError, "Formulae [%s] of %s and [%s] of %s have matching index id (%d)\n", formula->arch_name[0], formula->title, check->arch_name[0], check->title, formula->index);
303  }
304  numb++;
305  }
306 
307  LOG(llevDebug, "done checking.\n");
308 }
309 
317 void dump_alchemy(void) {
318  recipelist *fl = formulalist;
319  recipe *formula = NULL;
320  linked_char *next;
321  int num_ingred = 1;
322 
323  fprintf(logfile, "\n");
324  while (fl) {
325  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);
326  for (formula = fl->items; formula != NULL; formula = formula->next) {
327  const artifact *art = NULL;
328  char buf[MAX_BUF];
329  size_t i;
330 
331  for (i = 0; i < formula->arch_names; i++) {
332  const char *string = formula->arch_name[i];
333 
334  if (find_archetype(string) != NULL) {
335  art = locate_recipe_artifact(formula, i);
336  if (!art && strcmp(formula->title, "NONE"))
337  LOG(llevError, "Formula %s has no artifact\n", formula->title);
338  else {
339  if (strcmp(formula->title, "NONE"))
340  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
341  else
342  snprintf(buf, sizeof(buf), "%s", string);
343  fprintf(logfile, "%-30s(%d) bookchance %3d ", buf, formula->index, formula->chance);
344  fprintf(logfile, "skill %s", formula->skill);
345  fprintf(logfile, "\n");
346  if (formula->ingred != NULL) {
347  int nval = 0, tval = 0;
348  fprintf(logfile, "\tIngred: ");
349  for (next = formula->ingred; next != NULL; next = next->next) {
350  if (nval != 0)
351  fprintf(logfile, ",");
352  fprintf(logfile, "%s(%d)", next->name, (nval = strtoint(next->name)));
353  tval += nval;
354  }
355  fprintf(logfile, "\n");
356  if (tval != formula->index)
357  fprintf(logfile, "WARNING:ingredient list and formula values not equal.\n");
358  }
359  if (formula->skill != NULL)
360  fprintf(logfile, "\tSkill Required: %s", formula->skill);
361  if (formula->cauldron != NULL)
362  fprintf(logfile, "\tCauldron: %s\n", formula->cauldron);
363  fprintf(logfile, "\tDifficulty: %d\t Exp: %d\n", formula->diff, formula->exp);
364  }
365  } else
366  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
367  }
368  }
369  fprintf(logfile, "\n");
370  fl = fl->next;
371  num_ingred++;
372  }
373 }
374 
389 archetype *find_treasure_by_name(const treasure *t, const char *name, int depth) {
390  treasurelist *tl;
391  archetype *at;
392 
393  if (depth > 10)
394  return NULL;
395 
396  while (t != NULL) {
397  if (t->name != NULL) {
398  tl = find_treasurelist(t->name);
399  at = find_treasure_by_name(tl->items, name, depth+1);
400  if (at != NULL)
401  return at;
402  } else {
403  if (!strcasecmp(t->item->clone.name, name))
404  return t->item;
405  }
406  if (t->next_yes != NULL) {
407  at = find_treasure_by_name(t->next_yes, name, depth);
408  if (at != NULL)
409  return at;
410  }
411  if (t->next_no != NULL) {
412  at = find_treasure_by_name(t->next_no, name, depth);
413  if (at != NULL)
414  return at;
415  }
416  t = t->next;
417  }
418  return NULL;
419 }
420 
440 static long find_ingred_cost(const char *name) {
441  archetype *at;
442  archetype *at2;
443  const artifactlist *al;
444  const artifact *art;
445  long mult;
446  char *cp;
447  char part1[100];
448  char part2[100];
449 
450  /* same as atoi(), but skip number */
451  mult = 0;
452  while (isdigit(*name)) {
453  mult = 10*mult+(*name-'0');
454  name++;
455  }
456  if (mult > 0)
457  name++;
458  else
459  mult = 1;
460  /* first, try to match the name of an archetype */
461  for (at = first_archetype; at != NULL; at = at->next) {
462  if (at->clone.title != NULL) {
463  /* inefficient, but who cares? */
464  snprintf(part1, sizeof(part1), "%s %s", at->clone.name, at->clone.title);
465  if (!strcasecmp(part1, name))
466  return mult*at->clone.value;
467  }
468  if (!strcasecmp(at->clone.name, name))
469  return mult*at->clone.value;
470  }
471  /* second, try to match an artifact ("arch of something") */
472  cp = strstr(name, " of ");
473  if (cp != NULL) {
474  safe_strncpy(part1, name, sizeof(part1));
475  part1[cp-name] = '\0';
476  safe_strncpy(part2, cp + 4, sizeof(part2));
477  /* find the first archetype matching the first part of the name */
478  for (at = first_archetype; at != NULL; at = at->next)
479  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL)
480  break;
481  if (at != NULL) {
482  /* find the first artifact derived from that archetype (same type) */
483  for (al = first_artifactlist; al != NULL; al = al->next)
484  if (al->type == at->clone.type) {
485  for (art = al->items; art != NULL; art = art->next)
486  if (!strcasecmp(art->item->name, part2))
487  return mult*at->clone.value*art->item->value;
488  }
489  }
490  }
491  /* third, try to match a body part ("arch's something") */
492  cp = strstr(name, "'s ");
493  if (cp != NULL) {
494  safe_strncpy(part1, name, sizeof(part1));
495  part1[cp-name] = '\0';
496  safe_strncpy(part2, cp + 3, sizeof(part2));
497  /* examine all archetypes matching the first part of the name */
498  for (at = first_archetype; at != NULL; at = at->next)
499  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL) {
500  if (at->clone.randomitems != NULL) {
501  at2 = find_treasure_by_name(at->clone.randomitems->items, part2, 0);
502  if (at2 != NULL)
503  return mult*at2->clone.value*isqrt(at->clone.level*2);
504  }
505  }
506  }
507  /* failed to find any matching items -- formula should be checked */
508  return -1;
509 }
510 
519 void dump_alchemy_costs(void) {
520  recipelist *fl = formulalist;
521  recipe *formula = NULL;
522  linked_char *next;
523  int num_ingred = 1;
524  int num_errors = 0;
525  long cost;
526  long tcost;
527 
528  fprintf(logfile, "\n");
529  while (fl) {
530  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);
531  for (formula = fl->items; formula != NULL; formula = formula->next) {
532  const artifact *art = NULL;
533  const archetype *at = NULL;
534  char buf[MAX_BUF];
535  size_t i;
536 
537  for (i = 0; i < formula->arch_names; i++) {
538  const char *string = formula->arch_name[i];
539 
540  if ((at = find_archetype(string)) != NULL) {
541  art = locate_recipe_artifact(formula, i);
542  if (!art && strcmp(formula->title, "NONE"))
543  LOG(llevError, "Formula %s has no artifact\n", formula->title);
544  else {
545  if (!strcmp(formula->title, "NONE"))
546  snprintf(buf, sizeof(buf), "%s", string);
547  else
548  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
549  fprintf(logfile, "\n%-40s bookchance %3d skill %s\n", buf, formula->chance, formula->skill);
550  if (formula->ingred != NULL) {
551  tcost = 0;
552  for (next = formula->ingred; next != NULL; next = next->next) {
553  cost = find_ingred_cost(next->name);
554  if (cost < 0)
555  num_errors++;
556  fprintf(logfile, "\t%-33s%5ld\n", next->name, cost);
557  if (cost < 0 || tcost < 0)
558  tcost = -1;
559  else
560  tcost += cost;
561  }
562  if (art != NULL && art->item != NULL)
563  cost = at->clone.value*art->item->value;
564  else
565  cost = at->clone.value;
566  fprintf(logfile, "\t\tBuying result costs: %5ld", cost);
567  if (formula->yield > 1) {
568  fprintf(logfile, " to %ld (max %d items)\n", cost*formula->yield, formula->yield);
569  cost = cost*(formula->yield+1L)/2L;
570  } else
571  fprintf(logfile, "\n");
572  fprintf(logfile, "\t\tIngredients cost: %5ld\n\t\tComment: ", tcost);
573  if (tcost < 0)
574  fprintf(logfile, "Could not find some ingredients. Check the formula!\n");
575  else if (tcost > cost)
576  fprintf(logfile, "Ingredients are much too expensive. Useless formula.\n");
577  else if (tcost*2L > cost)
578  fprintf(logfile, "Ingredients are too expensive.\n");
579  else if (tcost*10L < cost)
580  fprintf(logfile, "Ingredients are too cheap.\n");
581  else
582  fprintf(logfile, "OK.\n");
583  }
584  }
585  } else
586  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
587  }
588  }
589  fprintf(logfile, "\n");
590  fl = fl->next;
591  num_ingred++;
592  }
593  if (num_errors > 0)
594  fprintf(logfile, "WARNING: %d objects required by the formulae do not exist in the game.\n", num_errors);
595 }
596 
605 static const char *ingred_name(const char *name) {
606  const char *cp = name;
607 
608  if (atoi(cp))
609  cp = strchr(cp, ' ')+1;
610  return cp;
611 }
612 
621 static int numb_ingred(const char *buf) {
622  int numb;
623 
624  if ((numb = atoi(buf)))
625  return numb;
626  else
627  return 1;
628 }
629 
640 int strtoint(const char *buf) {
641  const char *cp = ingred_name(buf);
642  int val = 0, len = strlen(cp), mult = numb_ingred(buf);
643 
644  while (len) {
645  val += tolower(*cp);
646  cp++; len--;
647  }
648  return val*mult;
649 }
650 
661 const artifact *locate_recipe_artifact(const recipe *rp, size_t idx) {
662  object *item = create_archetype(rp->arch_name[idx]);
663  const artifactlist *at = NULL;
664  const artifact *art = NULL;
665 
666  if (!item)
667  return (artifact *)NULL;
668 
669  if ((at = find_artifactlist(item->type)))
670  for (art = at->items; art; art = art->next)
671  if (!strcmp(art->item->name, rp->title) && legal_artifact_combination(item, art))
672  break;
673 
675 
676  return art;
677 }
678 
686  recipelist *fl = NULL;
687  int number = 0, roll = 0;
688 
689  /* first, determine # of recipelist we have */
690  for (fl = get_formulalist(1); fl; fl = fl->next)
691  number++;
692 
693  /* now, randomly choose one */
694  if (number > 0)
695  roll = RANDOM()%number;
696 
697  fl = get_formulalist(1);
698  while (roll && fl) {
699  if (fl->next)
700  fl = fl->next;
701  else
702  break;
703  roll--;
704  }
705  if (!fl) /* failed! */
706  LOG(llevError, "get_random_recipelist(): no recipelists found!\n");
707  else if (fl->total_chance == 0)
708  fl = get_random_recipelist();
709 
710  return fl;
711 }
712 
722  recipelist *fl = rpl;
723  recipe *rp = NULL;
724  int r = 0;
725 
726  /* looks like we have to choose a random one */
727  if (fl == NULL)
728  if ((fl = get_random_recipelist()) == NULL)
729  return rp;
730 
731  if (fl->total_chance > 0) {
732  r = RANDOM()%fl->total_chance;
733  for (rp = fl->items; rp; rp = rp->next) {
734  r -= rp->chance;
735  if (r < 0)
736  break;
737  }
738  }
739  return rp;
740 }
741 
745 void free_all_recipes(void) {
746  recipelist *fl, *flnext;
747  recipe *formula = NULL, *next;
748  linked_char *lchar, *charnext;
749 
750  LOG(llevDebug, "Freeing all the recipes\n");
751  for (fl = formulalist; fl != NULL; fl = flnext) {
752  flnext = fl->next;
753 
754  for (formula = fl->items; formula != NULL; formula = next) {
755  next = formula->next;
756 
757  free(formula->arch_name[0]);
758  free(formula->arch_name);
759  if (formula->title)
760  free_string(formula->title);
761  if (formula->skill)
762  free_string(formula->skill);
763  if (formula->cauldron)
764  free_string(formula->cauldron);
765  if (formula->failure_arch)
766  free_string(formula->failure_arch);
767  if (formula->failure_message)
768  free_string(formula->failure_message);
769  for (lchar = formula->ingred; lchar; lchar = charnext) {
770  charnext = lchar->next;
771  free_string(lchar->name);
772  free(lchar);
773  }
774  if (formula->tool)
775  free(formula->tool[0]);
776  free(formula->tool);
777  free(formula);
778  }
779  free(fl);
780  }
781  formulalist = NULL;
782 }
783 
795 static void build_stringlist(const char *str, char ***result_list, size_t *result_size) {
796  char *dup;
797  char *p;
798  size_t size;
799  size_t i;
800 
801  dup = strdup_local(str);
802  if (dup == NULL)
804 
805  size = 0;
806  for (p = strtok(dup, ","); p != NULL; p = strtok(NULL, ","))
807  size++;
808 
809  assert(size > 0);
810  *result_list = malloc(sizeof(**result_list) * size);
811  if (*result_list == NULL)
813  *result_size = size;
814 
815  for (i = 0; i < size; i++) {
816  (*result_list)[i] = dup;
817  dup = dup+strlen(dup)+1;
818  }
819 }
820 
828 recipe *find_recipe_for_tool(const char *tool, recipe *from) {
829  size_t t;
830  recipelist *list = from ? get_formulalist(from->ingred_count) : formulalist;
831  recipe *test = from ? from->next : list->items;
832 
833  while (list) {
834  while (test) {
835  for (t = 0; t < test->tool_size; t++) {
836  if (strcmp(test->tool[t], tool) == 0) {
837  return test;
838  }
839  }
840  test = test->next;
841  }
842 
843  list = list->next;
844  }
845 
846  return NULL;
847 }
EXTERN FILE * logfile
Used by server/daemon.c.
Definition: global.h:144
Error, serious thing.
Definition: logger.h:11
static void check_formulae(void)
Check if formula don&#39;t have the same index.
Definition: recipe.c:289
archetype * find_archetype(const char *name)
Finds, using the hashtable, which archetype matches the given name.
Definition: arch.c:695
uint8_t type
Object type that this list represents.
Definition: artifact.h:27
List of recipes with a certain number of ingredients.
Definition: recipe.h:37
int diff
Alchemical dfficulty level.
Definition: recipe.h:16
archetype * find_treasure_by_name(const treasure *t, const char *name, int depth)
Find a treasure with a matching name.
Definition: recipe.c:389
treasureliststruct represents one logical group of items to be generated together.
Definition: treasure.h:82
const artifactlist * find_artifactlist(int type)
Searches the artifact lists and returns one that has the same type of objects on it.
Definition: artifact.c:630
static void build_stringlist(const char *str, char ***result_list, size_t *result_size)
Split a comma separated string list into words.
Definition: recipe.c:795
recipe * get_random_recipe(recipelist *rpl)
Gets a random recipe from a list, based on chance.
Definition: recipe.c:721
#define strdup_local
Definition: compat.h:25
struct recipeliststruct * next
Pointer to next recipe list.
Definition: recipe.h:41
int number
Number of recipes in this list.
Definition: recipe.h:39
static int check_recipe(const recipe *rp)
Makes sure we actually have the requested artifact and archetype.
Definition: recipe.c:136
int yield
Maximum number of items produced by the recipe.
Definition: recipe.h:21
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.c:596
struct artifactstruct * items
Artifacts for this type.
Definition: artifact.h:30
treasurelist * find_treasurelist(const char *name)
Searches for the given treasurelist in the globally linked list of treasurelists which has been built...
Definition: treasure.c:292
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
struct treasureliststruct * randomitems
Items to be generated.
Definition: object.h:385
object clone
An object from which to do object_copy()
Definition: object.h:470
linked_char * ingred
List of ingredients.
Definition: recipe.h:22
recipe * find_recipe_for_tool(const char *tool, recipe *from)
Find a recipe for a specified tool.
Definition: recipe.c:828
int isqrt(int n)
Compute the square root.
Definition: utils.c:585
static int numb_ingred(const char *buf)
Extracts the number part of an ingredient.
Definition: recipe.c:621
static recipelist * init_recipelist(void)
Allocates a new recipelist.
Definition: recipe.c:58
treasure is one element in a linked list, which together consist of a complete treasure-list.
Definition: treasure.h:63
int is_combination
Whather this is an alchemy recipe, or an item transformation description.
Definition: recipe.h:31
int transmute
If defined, one of the formula ingredients is used as the basis for the product object.
Definition: recipe.h:19
Global type definitions and header inclusions.
#define safe_strncpy
Definition: compat.h:23
static recipelist * get_random_recipelist(void)
Gets a random recipe list.
Definition: recipe.c:685
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
void dump_alchemy_costs(void)
Dumps to output all costs of recipes.
Definition: recipe.c:519
struct archt * item
Which item this link can be.
Definition: treasure.h:64
void init_formulae(void)
Builds up the lists of formula from the file in the libdir.
Definition: recipe.c:161
int ingred_count
Number of items in ingred.
Definition: recipe.h:23
int chance
Chance that recipe for this item will appear in an alchemical grimore.
Definition: recipe.h:14
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
const char * title
Of foo, etc.
Definition: object.h:317
int legal_artifact_combination(const object *op, const artifact *art)
Checks if op can be combined with art.
Definition: artifact.c:221
struct artifactliststruct * next
Next list of artifacts.
Definition: artifact.h:29
sstring title
Distinguishing name of product.
Definition: recipe.h:11
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
Definition: arch.c:620
char ** arch_name
Possible archetypes of the final product made.
Definition: recipe.h:13
static const char * ingred_name(const char *name)
Extracts the name from an ingredient.
Definition: recipe.c:605
int total_chance
Total chance of the recipes in this list.
Definition: recipe.h:38
const artifact * locate_recipe_artifact(const recipe *rp, size_t idx)
Finds an artifact for a recipe.
Definition: recipe.c:661
#define snprintf
Definition: win32.h:46
void dump_alchemy(void)
Dumps alchemy recipes to output.
Definition: recipe.c:317
struct linked_char * next
Definition: global.h:88
int strtoint(const char *buf)
Convert buf into an integer equal to the coadded sum of the (lowercase) character.
Definition: recipe.c:640
const char * name
The name of the object, obviously...
Definition: object.h:311
This represents all archetypes for one particular object type.
Definition: artifact.h:26
struct treasurestruct * next_no
If this item was not generated, then continue here.
Definition: treasure.h:68
sstring skill
Skill name used to make this recipe.
Definition: recipe.h:26
EXTERN artifactlist * first_artifactlist
First artifact.
Definition: global.h:121
static recipelist * formulalist
Pointer to first recipelist.
Definition: recipe.c:48
int index
Index value derived from formula ingredients.
Definition: recipe.h:18
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
This is one artifact, ie one special item.
Definition: artifact.h:14
size_t tool_size
Length of tool.
Definition: recipe.h:33
struct treasurestruct * items
Items in this list, linked.
Definition: treasure.h:90
#define tolower(C)
Simple macro to convert a letter to lowercase.
Definition: c_new.c:29
void free_all_recipes(void)
Frees all memory allocated to recipes and recipes lists.
Definition: recipe.c:745
int exp
How much exp to give for this formulae.
Definition: recipe.h:17
const char * datadir
Read only data files.
Definition: global.h:244
const char * name
Definition: global.h:87
Object structure, the core of Crossfire.
struct treasurestruct * next_yes
If this item was generated, use this link instead of ->next.
Definition: treasure.h:67
#define RANDOM()
Definition: define.h:679
size_t arch_names
Size of the arch_name[] array.
Definition: recipe.h:12
Only for debugging purposes.
Definition: logger.h:13
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
sstring failure_message
Specific failure message.
Definition: recipe.h:29
struct archt * next
Next archetype in a linked list.
Definition: object.h:467
struct recipestruct * next
Next recipe with the same number of ingredients.
Definition: recipe.h:24
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
int strcasecmp(const char *s1, const char *s2)
Case-insensitive comparaison of strings.
Definition: porting.c:256
sstring failure_arch
Arch of the item to generate on failure, instead of blowing up stuff.
Definition: recipe.h:28
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
static long find_ingred_cost(const char *name)
Try to find an ingredient with specified name.
Definition: recipe.c:440
object * item
Special values of the artifact.
Definition: artifact.h:15
static recipe * get_empty_formula(void)
Allocates a new recipe.
Definition: recipe.c:77
struct treasurestruct * next
Next treasure-item in a linked list.
Definition: treasure.h:66
int16_t level
Level of creature or object.
Definition: object.h:351
const char * name
If non null, name of list to use instead.
Definition: treasure.h:65
EXTERN archetype * first_archetype
First archetype.
Definition: global.h:122
int32_t value
How much money it is worth (or contains)
Definition: object.h:350
sstring cauldron
Arch of the cauldron/workbench used to house the formulae.
Definition: recipe.h:27
char ** tool
Tool(s) for item transformation.
Definition: recipe.h:32
sstring keycode
Optional keycode needed to use the recipe.
Definition: recipe.h:25
struct recipestruct * items
Pointer to first recipe in this list.
Definition: recipe.h:40
recipelist * get_formulalist(int i)
Gets a formula list by ingredients count.
Definition: recipe.c:114
int min_level
Minimum level to have in the skill to be able to use the formulae.
Definition: recipe.h:30
struct artifactstruct * next
Next artifact in the list.
Definition: artifact.h:18
One alchemy recipe.
Definition: recipe.h:10