Crossfire Server, Trunk
recipe.cpp
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 #include <memory>
42 
43 #include "object.h"
44 #include "assets.h"
45 #include "AssetsManager.h"
46 
47 static void build_stringlist(const char *str, char ***result_list, size_t *result_size);
48 
51 
60 static recipelist *init_recipelist(void) {
61  recipelist *tl = (recipelist *)malloc(sizeof(recipelist));
62  if (tl == NULL)
64  tl->total_chance = 0;
65  tl->number = 0;
66  tl->items = NULL;
67  tl->next = NULL;
68  return tl;
69 }
70 
79 static recipe *get_empty_formula(void) {
80  // This used to be a malloc followed by setting everything to zero.
81  // So just use calloc to make it faster.
82  // SilverNexus -- 2018-10-22
83  recipe *t = (recipe *)calloc(1, sizeof(recipe));
84  if (t == NULL)
86  return t;
87 }
88 
99  recipelist *fl = formulalist;
100  int number = i;
101 
102  while (fl && number > 1) {
103  if (!(fl = fl->next))
104  break;
105  number--;
106  }
107  return fl;
108 }
109 
120 static int check_recipe(const recipe *rp) {
121  size_t i;
122  int result;
123 
124  result = 1;
125  for (i = 0; i < rp->arch_names; i++) {
126  if (try_find_archetype(rp->arch_name[i]) != NULL) {
127  if (strcmp(rp->title, "NONE")) {
128  const artifact *art = locate_recipe_artifact(rp, i);
129 
130  if (!art) {
131  LOG(llevError, "Formula %s of %s has no artifact.\n", rp->arch_name[i], rp->title);
132  result = 0;
133  }
134  }
135  } else {
136  LOG(llevError, "Can't find archetype %s for formula %s\n", rp->arch_name[i], rp->title);
137  result = 0;
138  }
139  }
140 
141  return result;
142 }
143 
148  const recipelist *rl = formulalist;
149  int abort = 0;
150  while (rl) {
151  const recipe *rp = rl->items;
152  while (rp) {
153  if (!check_recipe(rp)) {
154  abort = 1;
155  }
156  rp = rp->next;
157  }
158  rl = rl->next;
159  }
160  return !abort;
161 }
162 
166 void init_formulae(BufferReader *reader, const char *filename) {
167  char *buf, *cp, *next;
168  recipe *formula = NULL;
169  recipelist *fl;
170  linked_char *tmp;
171  int value;
172 
173  if (!formulalist)
175 
176  while ((buf = bufferreader_next_line(reader)) != NULL) {
177  if (*buf == '#' || *buf == '\0')
178  continue;
179  cp = buf;
180  while (*cp == ' ') /* Skip blanks */
181  cp++;
182 
183  if (!strncmp(cp, "Remove ", 7)) {
184  if (strcmp(cp + 7, "*") == 0) {
187  } else {
188  LOG(llevError, "Recipes: only '*' is accepted for 'Remove' at %s:%zu\n", filename, bufferreader_current_line(reader));
189  }
190  continue;
191  }
192  if (!strncmp(cp, "Object", 6)) {
193  formula = get_empty_formula();
194  formula->title = add_string(strchr(cp, ' ')+1);
195  } else if (formula == NULL) {
196  LOG(llevError, "recipe.c: First key in formulae file %s is not \"Object\".\n", filename);
198  } else if (!strncmp(cp, "keycode", 7)) {
199  formula->keycode = add_string(strchr(cp, ' ')+1);
200  } else if (sscanf(cp, "trans %d", &value)) {
201  formula->transmute = value;
202  } else if (sscanf(cp, "yield %d", &value)) {
203  formula->yield = value;
204  } else if (sscanf(cp, "chance %d", &value)) {
205  formula->chance = value;
206  } else if (sscanf(cp, "exp %d", &value)) {
207  formula->exp = value;
208  } else if (sscanf(cp, "diff %d", &value)) {
209  formula->diff = value;
210  } else if (!strncmp(cp, "ingred", 6)) {
211  int numb_ingred;
212  formula->ingred_count = 1;
213  cp = strchr(cp, ' ')+1;
214  do {
215  if ((next = strchr(cp, ',')) != NULL) {
216  *(next++) = '\0';
217  formula->ingred_count++;
218  }
219  tmp = (linked_char *)malloc(sizeof(linked_char));
220  /* trim the string */
221  while (*cp == ' ')
222  cp++;
223  while (*cp != '\0' && cp[strlen(cp) - 1] == ' ')
224  cp[strlen(cp) - 1] = '\0';
225  tmp->name = add_string(cp);
226  tmp->next = formula->ingred;
227  formula->ingred = tmp;
228  /* each ingredient's ASCII value is coadded. Later on this
229  * value will be used allow us to search the formula lists
230  * quickly for the right recipe.
231  */
232  formula->index += strtoint(cp);
233  } while ((cp = next) != NULL);
234  /* now find the correct (# of ingred ordered) formulalist */
235  numb_ingred = formula->ingred_count;
236  fl = formulalist;
237  while (numb_ingred != 1) {
238  if (!fl->next)
239  fl->next = init_recipelist();
240  fl = fl->next;
241  numb_ingred--;
242  }
243  formula->next = fl->items;
244  fl->items = formula;
245  } else if (!strncmp(cp, "arch", 4)) {
246  build_stringlist(strchr(cp, ' ')+1, &formula->arch_name, &formula->arch_names);
247  } else if (!strncmp(cp, "skill", 5)) {
248  formula->skill = add_string(strchr(cp, ' ')+1);
249  } else if (!strncmp(cp, "cauldron", 8)) {
250  formula->cauldron = add_string(strchr(cp, ' ')+1);
251  } else if (!strncmp(cp, "failure_arch ", 13)) {
252  formula->failure_arch = add_string(strchr(cp, ' ')+1);
253  } else if (!strncmp(cp, "failure_message ", 16)) {
254  formula->failure_message = add_string(strchr(cp, ' ')+1);
255  } else if (sscanf(cp, "min_level %d", &value)) {
256  formula->min_level = value;
257  } else if (!strncmp(cp, "tool ", 5)) {
258  build_stringlist(strchr(cp, ' ')+1, &formula->tool, &formula->tool_size);
259  } else if (sscanf(cp, "combination %d", &value)) {
260  formula->is_combination = value ? 1 : 0;
261  } else
262  LOG(llevError, "Unknown input in file %s: %s\n", filename, buf);
263  }
264  /* Set the total chance and count for each formula list.
265  * This needs to be done at the end to avoid dependancies on the field order in the file
266  */
267  for (fl = formulalist; fl; fl = fl->next) {
268  fl->total_chance = 0;
269  fl->number = 0;
270  for (formula = fl->items; formula; formula = formula->next) {
271  fl->total_chance += formula->chance;
272  fl->number++;
273  }
274  }
275  LOG(llevDebug, "done.\n");
276 }
277 
292 bool check_formulae(void) {
293  recipelist *fl;
294  recipe *check, *formula;
295  int numb = 1, tool_match;
296  size_t tool_i,tool_j;
297  bool success = true;
298 
299  LOG(llevDebug, "Checking formulae lists...\n");
300 
301  for (fl = formulalist; fl != NULL; fl = fl->next) {
302  for (formula = fl->items; formula != NULL; formula = formula->next) {
303  for (check = formula->next; check != NULL; check = check->next)
304  /* If one recipe has a tool and another a caudron, we should be able to handle it */
305  if (check->index == formula->index && check->cauldron == formula->cauldron && (check->tool_size == formula->tool_size)) {
306  /* Check the tool list to make sure they have no matches */
307  if (check->tool_size > 0 && check->tool && formula->tool)
308  {
309  tool_match = 0;
310  for (tool_i = 0; tool_i < formula->tool_size; ++tool_i)
311  /* If it turns out these lists are sorted, then we could optimize this better. */
312  for (tool_j = 0; tool_j < check->tool_size; ++tool_j)
313  if (strcmp(formula->tool[tool_i], check->tool[tool_j]) == 0) {
314  tool_match = 1;
315  break; /* TODO: break out of the double loop */
316  }
317  }
318  else
319  tool_match = 1; /* If we get here, we matched on the cauldron */
320  /* Check to see if we have a denoted match */
321  if (tool_match) {
322  /* if the recipes don't have the same facility, then no issue anyway. */
323  LOG(llevError, " ERROR: On %d ingred list:\n", numb);
324  LOG(llevError, "Formulae [%s] of %s and [%s] of %s have matching index id (%d)\n",
325  formula->arch_name[0], formula->title, check->arch_name[0], check->title, formula->index);
326  success = false;
327  }
328  }
329  for (size_t idx = 0; idx < formula->arch_names; idx++) {
330  if (try_find_archetype(formula->arch_name[idx]) == NULL) {
331  LOG(llevError, "Formulae %s of %s (%d ingredients) references non existent archetype %s\n",
332  formula->arch_name[0], formula->title, numb, formula->arch_name[idx]);
333  success = false;
334  }
335  }
336  }
337  numb++;
338  }
339 
340  return success;
341 }
342 
350 void dump_alchemy(void) {
351  recipelist *fl = formulalist;
352  recipe *formula = NULL;
353  linked_char *next;
354  int num_ingred = 1;
355 
356  fprintf(logfile, "\n");
357  while (fl) {
358  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);
359  for (formula = fl->items; formula != NULL; formula = formula->next) {
360  const artifact *art = NULL;
361  char buf[MAX_BUF];
362  size_t i;
363 
364  for (i = 0; i < formula->arch_names; i++) {
365  const char *string = formula->arch_name[i];
366 
367  if (try_find_archetype(string) != NULL) {
368  art = locate_recipe_artifact(formula, i);
369  if (!art && strcmp(formula->title, "NONE"))
370  LOG(llevError, "Formula %s has no artifact\n", formula->title);
371  else {
372  if (strcmp(formula->title, "NONE"))
373  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
374  else
375  strlcpy(buf, string, sizeof(buf));
376  fprintf(logfile, "%-30s(%d) bookchance %3d ", buf, formula->index, formula->chance);
377  fprintf(logfile, "skill %s", formula->skill);
378  fprintf(logfile, "\n");
379  if (formula->ingred != NULL) {
380  int nval = 0, tval = 0;
381  fprintf(logfile, "\tIngred: ");
382  for (next = formula->ingred; next != NULL; next = next->next) {
383  if (nval != 0)
384  fprintf(logfile, ",");
385  fprintf(logfile, "%s(%d)", next->name, (nval = strtoint(next->name)));
386  tval += nval;
387  }
388  fprintf(logfile, "\n");
389  if (tval != formula->index)
390  fprintf(logfile, "WARNING:ingredient list and formula values not equal.\n");
391  }
392  if (formula->skill != NULL)
393  fprintf(logfile, "\tSkill Required: %s", formula->skill);
394  if (formula->cauldron != NULL)
395  fprintf(logfile, "\tCauldron: %s\n", formula->cauldron);
396  fprintf(logfile, "\tDifficulty: %d\t Exp: %d\n", formula->diff, formula->exp);
397  }
398  } else
399  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
400  }
401  }
402  fprintf(logfile, "\n");
403  fl = fl->next;
404  num_ingred++;
405  }
406 }
407 
422 archetype *find_treasure_by_name(const treasure *t, const char *name, int depth) {
423  treasurelist *tl;
424  archetype *at;
425 
426  if (depth > 10)
427  return NULL;
428 
429  while (t != NULL) {
430  if (t->name != NULL) {
431  tl = find_treasurelist(t->name);
432  at = find_treasure_by_name(tl->items, name, depth+1);
433  if (at != NULL)
434  return at;
435  } else {
436  if (!strcasecmp(t->item->clone.name, name))
437  return t->item;
438  }
439  if (t->next_yes != NULL) {
440  at = find_treasure_by_name(t->next_yes, name, depth);
441  if (at != NULL)
442  return at;
443  }
444  if (t->next_no != NULL) {
445  at = find_treasure_by_name(t->next_no, name, depth);
446  if (at != NULL)
447  return at;
448  }
449  t = t->next;
450  }
451  return NULL;
452 }
453 
473 static long recipe_find_ingredient_cost(const char *name) {
474  long mult;
475  const char *cp;
476  char part1[100];
477  char part2[100];
478 
479  /* same as atoi(), but skip number */
480  mult = 0;
481  while (isdigit(*name)) {
482  mult = 10*mult+(*name-'0');
483  name++;
484  }
485  if (mult > 0)
486  name++;
487  else
488  mult = 1;
489  /* first, try to match the name of an archetype */
490 
491  long value = 0;
492  bool found = false;
493  getManager()->archetypes()->each([&value, &found, &name, &part1] (const archetype *at) {
494  if (found) {
495  return;
496  }
497 
498  if (at->clone.title != NULL) {
499  /* inefficient, but who cares? */
500  snprintf(part1, sizeof(part1), "%s %s", at->clone.name, at->clone.title);
501  if (!strcasecmp(part1, name)) {
502  value = at->clone.value;
503  found = true;
504  return;
505  }
506  }
507  if (!strcasecmp(at->clone.name, name)) {
508  value = at->clone.value;
509  found = true;
510  return;
511  }
512  });
513  if (found) {
514  return mult * value;
515  }
516 
517  /* second, try to match an artifact ("arch of something") */
518  cp = strstr(name, " of ");
519  if (cp != NULL) {
520  safe_strncpy(part1, name, sizeof(part1));
521  part1[cp-name] = '\0';
522  safe_strncpy(part2, cp + 4, sizeof(part2));
523  getManager()->archetypes()->each([&value, &found, &part1, &part2] (const archetype *at) {
524  if (found) {
525  return;
526  }
527 
528  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL) {
529  /* find the first artifact derived from that archetype (same type) */
530  for (auto al = first_artifactlist; al != NULL; al = al->next) {
531  if (al->type == at->clone.type) {
532  for (const auto art : al->items) {
533  if (!strcasecmp(art->item->name, part2)) {
534  value = at->clone.value * art->item->value;
535  found = true;
536  return;
537  }
538  }
539  }
540  }
541  }
542  });
543  }
544  if (found) {
545  return mult * value;
546  }
547 
548  /* third, try to match a body part ("arch's something") */
549  cp = strstr(name, "'s ");
550  if (cp != NULL) {
551  safe_strncpy(part1, name, sizeof(part1));
552  part1[cp-name] = '\0';
553  safe_strncpy(part2, cp + 3, sizeof(part2));
554  /* examine all archetypes matching the first part of the name */
555  getManager()->archetypes()->each([&value, &found, &part1, &part2] (const archetype *at) {
556  if (found) {
557  return;
558  }
559  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL) {
560  if (at->clone.randomitems != NULL) {
561  auto at2 = find_treasure_by_name(at->clone.randomitems->items, part2, 0);
562  if (at2 != NULL) {
563  value = at2->clone.value * isqrt(at->clone.level * 2);
564  found = true;
565  return;
566  }
567  }
568  }
569  });
570  }
571  if (found) {
572  return mult * value;
573  }
574 
575  /* failed to find any matching items -- formula should be checked */
576  LOG(llevError, "Couldn't find cost for ingredient %s\n", name);
577  return -1;
578 }
579 
588 void dump_alchemy_costs(void) {
589  recipelist *fl = formulalist;
590  recipe *formula = NULL;
591  linked_char *next;
592  int num_ingred = 1;
593  int num_errors = 0;
594  long cost;
595  long tcost;
596 
597  fprintf(logfile, "\n");
598  while (fl) {
599  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);
600  for (formula = fl->items; formula != NULL; formula = formula->next) {
601  const artifact *art = NULL;
602  const archetype *at = NULL;
603  char buf[MAX_BUF];
604  size_t i;
605 
606  for (i = 0; i < formula->arch_names; i++) {
607  const char *string = formula->arch_name[i];
608 
609  if ((at = try_find_archetype(string)) != NULL) {
610  art = locate_recipe_artifact(formula, i);
611  if (!art && strcmp(formula->title, "NONE"))
612  LOG(llevError, "Formula %s has no artifact\n", formula->title);
613  else {
614  if (!strcmp(formula->title, "NONE"))
615  strlcpy(buf, string, sizeof(buf));
616  else
617  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
618  fprintf(logfile, "\n%-40s bookchance %3d skill %s\n", buf, formula->chance, formula->skill);
619  if (formula->ingred != NULL) {
620  tcost = 0;
621  for (next = formula->ingred; next != NULL; next = next->next) {
623  if (cost < 0)
624  num_errors++;
625  fprintf(logfile, "\t%-33s%5ld\n", next->name, cost);
626  if (cost < 0 || tcost < 0)
627  tcost = -1;
628  else
629  tcost += cost;
630  }
631  if (art != NULL && art->item != NULL)
632  cost = at->clone.value*art->item->value;
633  else
634  cost = at->clone.value;
635  fprintf(logfile, "\t\tBuying result costs: %5ld", cost);
636  if (formula->yield > 1) {
637  fprintf(logfile, " to %ld (max %d items)\n", cost*formula->yield, formula->yield);
638  cost = cost*(formula->yield+1L)/2L;
639  } else
640  fprintf(logfile, "\n");
641  fprintf(logfile, "\t\tIngredients cost: %5ld\n\t\tComment: ", tcost);
642  if (tcost < 0)
643  fprintf(logfile, "Could not find some ingredients. Check the formula!\n");
644  else if (tcost > cost)
645  fprintf(logfile, "Ingredients are much too expensive. Useless formula.\n");
646  else if (tcost*2L > cost)
647  fprintf(logfile, "Ingredients are too expensive.\n");
648  else if (tcost*10L < cost)
649  fprintf(logfile, "Ingredients are too cheap.\n");
650  else
651  fprintf(logfile, "OK.\n");
652  }
653  }
654  } else
655  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
656  }
657  }
658  fprintf(logfile, "\n");
659  fl = fl->next;
660  num_ingred++;
661  }
662  if (num_errors > 0)
663  fprintf(logfile, "WARNING: %d objects required by the formulae do not exist in the game.\n", num_errors);
664 }
665 
674 static const char *ingred_name(const char *name) {
675  const char *cp = name;
676 
677  if (atoi(cp))
678  cp = strchr(cp, ' ')+1;
679  return cp;
680 }
681 
690 static int numb_ingred(const char *buf) {
691  int numb;
692 
693  if ((numb = atoi(buf)))
694  return numb;
695  else
696  return 1;
697 }
698 
709 int strtoint(const char *buf) {
710  const char *cp = ingred_name(buf);
711  int val = 0, len = strlen(cp), mult = numb_ingred(buf);
712 
713  while (len) {
714  val += tolower(*cp);
715  cp++; len--;
716  }
717  return val*mult;
718 }
719 
730 const artifact *locate_recipe_artifact(const recipe *rp, size_t idx) {
731  std::unique_ptr<object, void(*)(object *)> item(create_archetype(rp->arch_name[idx]), object_free_drop_inventory);
732  const artifactlist *at = NULL;
733 
734  if (!item)
735  return (artifact *)NULL;
736 
737  if ((at = find_artifactlist(item->type)))
738  for (auto art : at->items)
739  if (!strcmp(art->item->name, rp->title) && legal_artifact_combination(item.get(), art))
740  return art;
741 
742  return nullptr;
743 }
744 
752  recipelist *fl = NULL;
753  int number = 0, roll = 0;
754 
755  /* first, determine # of recipelist we have */
756  for (fl = get_formulalist(1); fl; fl = fl->next)
757  number++;
758 
759  /* now, randomly choose one */
760  if (number > 0)
761  roll = RANDOM()%number;
762 
763  fl = get_formulalist(1);
764  while (roll && fl) {
765  if (fl->next)
766  fl = fl->next;
767  else
768  break;
769  roll--;
770  }
771  if (!fl) /* failed! */
772  LOG(llevError, "get_random_recipelist(): no recipelists found!\n");
773  else if (fl->total_chance == 0)
774  fl = get_random_recipelist();
775 
776  return fl;
777 }
778 
788  recipelist *fl = rpl;
789  recipe *rp = NULL;
790  int r = 0;
791 
792  /* looks like we have to choose a random one */
793  if (fl == NULL)
794  if ((fl = get_random_recipelist()) == NULL)
795  return rp;
796 
797  if (fl->total_chance > 0) {
798  r = RANDOM()%fl->total_chance;
799  for (rp = fl->items; rp; rp = rp->next) {
800  r -= rp->chance;
801  if (r < 0)
802  break;
803  }
804  }
805  return rp;
806 }
807 
811 void free_all_recipes(void) {
812  recipelist *fl, *flnext;
813  recipe *formula = NULL, *next;
814  linked_char *lchar, *charnext;
815 
816  LOG(llevDebug, "Freeing all the recipes\n");
817  for (fl = formulalist; fl != NULL; fl = flnext) {
818  flnext = fl->next;
819 
820  for (formula = fl->items; formula != NULL; formula = next) {
821  next = formula->next;
822 
823  free(formula->arch_name[0]);
824  free(formula->arch_name);
825  if (formula->title)
826  free_string(formula->title);
827  if (formula->skill)
828  free_string(formula->skill);
829  if (formula->cauldron)
830  free_string(formula->cauldron);
831  if (formula->failure_arch)
832  free_string(formula->failure_arch);
833  if (formula->failure_message)
834  free_string(formula->failure_message);
835  for (lchar = formula->ingred; lchar; lchar = charnext) {
836  charnext = lchar->next;
837  free_string(lchar->name);
838  free(lchar);
839  }
840  if (formula->tool)
841  free(formula->tool[0]);
842  free(formula->tool);
843  free(formula);
844  }
845  free(fl);
846  }
847  formulalist = NULL;
848 }
849 
861 static void build_stringlist(const char *str, char ***result_list, size_t *result_size) {
862  char *dup;
863  char *p;
864  size_t size;
865  size_t i;
866 
867  dup = strdup_local(str);
868  if (dup == NULL)
870 
871  size = 0;
872  for (p = strtok(dup, ","); p != NULL; p = strtok(NULL, ","))
873  size++;
874 
875  assert(size > 0);
876  *result_list = static_cast<char **>(malloc(sizeof(**result_list) * size));
877  if (*result_list == NULL)
879  *result_size = size;
880 
881  for (i = 0; i < size; i++) {
882  (*result_list)[i] = dup;
883  dup = dup+strlen(dup)+1;
884  }
885 }
886 
894 recipe *find_recipe_for_tool(const char *tool, recipe *from) {
895  size_t t;
897  recipe *test = from ? from->next : list->items;
898 
899  while (list) {
900  while (test) {
901  for (t = 0; t < test->tool_size; t++) {
902  if (strcmp(test->tool[t], tool) == 0) {
903  return test;
904  }
905  }
906  test = test->next;
907  }
908 
909  list = list->next;
910  }
911 
912  return NULL;
913 }
914 
920 const Face *recipe_get_face(const recipe *rp) {
921  const artifact *art;
922  archetype *arch;
923  object *item;
924  const Face *face;
925 
926  if (rp->arch_names == 0)
927  return NULL;
928 
930  if (arch == NULL) {
931  return NULL;
932  }
933  if (strcmp(rp->title, "NONE") == 0) {
934  return arch->clone.face;
935  }
936 
937  art = locate_recipe_artifact(rp, 0);
938  if (art == NULL)
939  return arch->clone.face;
940 
941  face = arch->clone.face;
945  if (item->face != NULL && item->face != blank_face)
946  face = item->face;
948 
949  return face;
950 }
find_recipe_for_tool
recipe * find_recipe_for_tool(const char *tool, recipe *from)
Definition: recipe.cpp:894
give.next
def next
Definition: give.py:44
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:536
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
get_formulalist
recipelist * get_formulalist(int i)
Definition: recipe.cpp:98
recipe::tool_size
size_t tool_size
Definition: recipe.h:33
bufferreader_current_line
size_t bufferreader_current_line(BufferReader *br)
Definition: bufferreader.cpp:140
llevError
@ llevError
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
strdup_local
#define strdup_local
Definition: compat.h:29
recipe::arch_names
size_t arch_names
Definition: recipe.h:12
object
I ve redone this file to hopefully make it a little easier to read through and quickly get some idea what to do There are sections section is current programming style hints for developers to make things easier Section is programming guide for new addition Section is notes for making patches Section currently used conventions hints for new code ob is for object
Definition: style-guide.txt:11
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
treasurelist::items
treasure * items
Definition: treasure.h:92
dump_alchemy_costs
void dump_alchemy_costs(void)
Definition: recipe.cpp:588
init_recipelist
static recipelist * init_recipelist(void)
Definition: recipe.cpp:60
recipe::yield
int yield
Definition: recipe.h:21
get_random_recipelist
static recipelist * get_random_recipelist(void)
Definition: recipe.cpp:751
recipe::failure_arch
sstring failure_arch
Definition: recipe.h:28
guildoracle.list
list
Definition: guildoracle.py:87
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:230
recipelist::next
recipelist * next
Definition: recipe.h:41
artifact::item
object * item
Definition: artifact.h:15
recipelist::items
recipe * items
Definition: recipe.h:40
Ice.tmp
int tmp
Definition: Ice.py:207
check_recipe
static int check_recipe(const recipe *rp)
Definition: recipe.cpp:120
tolower
#define tolower(C)
Definition: c_new.cpp:30
find_treasurelist
treasurelist * find_treasurelist(const char *name)
Definition: assets.cpp:249
recipe::failure_message
sstring failure_message
Definition: recipe.h:29
recipe::arch_name
char ** arch_name
Definition: recipe.h:13
blank_face
const Face * blank_face
Definition: image.cpp:36
SEE_LAST_ERROR
@ SEE_LAST_ERROR
Definition: define.h:52
recipe::transmute
int transmute
Definition: recipe.h:19
npc_dialog.filename
filename
Definition: npc_dialog.py:99
object::title
sstring title
Definition: object.h:325
recipe_find_ingredient_cost
static long recipe_find_ingredient_cost(const char *name)
Definition: recipe.cpp:473
AssetsManager.h
recipe::exp
int exp
Definition: recipe.h:17
check_recipes
bool check_recipes()
Definition: recipe.cpp:147
buf
StringBuffer * buf
Definition: readable.cpp:1552
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
recipelist::total_chance
int total_chance
Definition: recipe.h:38
formulalist
static recipelist * formulalist
Definition: recipe.cpp:50
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
linked_char
Definition: global.h:96
recipe::is_combination
int is_combination
Definition: recipe.h:31
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1555
linked_char::name
const char * name
Definition: global.h:97
recipelist
Definition: recipe.h:37
rotate-tower.result
bool result
Definition: rotate-tower.py:13
treasurelist
Definition: treasure.h:85
archetype::clone
object clone
Definition: object.h:478
check_formulae
bool check_formulae(void)
Definition: recipe.cpp:292
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
make_face_from_files.str
str
Definition: make_face_from_files.py:30
object::value
int32_t value
Definition: object.h:360
recipe::index
int index
Definition: recipe.h:18
numb_ingred
static int numb_ingred(const char *buf)
Definition: recipe.cpp:690
linked_char::next
struct linked_char * next
Definition: global.h:98
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1587
artifactlist
Definition: artifact.h:24
AssetsManager::archetypes
Archetypes * archetypes()
Definition: AssetsManager.h:44
archetype
Definition: object.h:474
logfile
FILE * logfile
Definition: init.cpp:114
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
recipe::ingred_count
int ingred_count
Definition: recipe.h:23
MAX_BUF
#define MAX_BUF
Definition: define.h:35
free_all_recipes
void free_all_recipes(void)
Definition: recipe.cpp:811
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
RANDOM
#define RANDOM()
Definition: define.h:644
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
recipe
Definition: recipe.h:10
recipe::tool
char ** tool
Definition: recipe.h:32
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:570
object::name
sstring name
Definition: object.h:319
get_random_recipe
recipe * get_random_recipe(recipelist *rpl)
Definition: recipe.cpp:787
bigchest.check
check
Definition: bigchest.py:10
locate_recipe_artifact
const artifact * locate_recipe_artifact(const recipe *rp, size_t idx)
Definition: recipe.cpp:730
AssetsCollection::each
void each(std::function< void(T *)> op)
Definition: AssetsCollection.h:158
ingred_name
static const char * ingred_name(const char *name)
Definition: recipe.cpp:674
find_treasure_by_name
archetype * find_treasure_by_name(const treasure *t, const char *name, int depth)
Definition: recipe.cpp:422
recipe::chance
int chance
Definition: recipe.h:14
item
Definition: item.py:1
BufferReader
Definition: bufferreader.cpp:21
autojail.value
value
Definition: autojail.py:6
Floor.t
t
Definition: Floor.py:62
dump_alchemy
void dump_alchemy(void)
Definition: recipe.cpp:350
strtoint
int strtoint(const char *buf)
Definition: recipe.cpp:709
recipe::diff
int diff
Definition: recipe.h:16
assets.h
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
object_give_identified_properties
void object_give_identified_properties(object *op)
Definition: item.cpp:1360
init_formulae
void init_formulae(BufferReader *reader, const char *filename)
Definition: recipe.cpp:166
strcasecmp
int strcasecmp(const char *s1, const char *s2)
recipe::keycode
sstring keycode
Definition: recipe.h:25
recipelist::number
int number
Definition: recipe.h:39
Face
Definition: face.h:14
recipe::min_level
int min_level
Definition: recipe.h:30
get_empty_formula
static recipe * get_empty_formula(void)
Definition: recipe.cpp:79
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
recipe::ingred
linked_char * ingred
Definition: recipe.h:22
FREE_OBJ_FREE_INVENTORY
#define FREE_OBJ_FREE_INVENTORY
Definition: object.h:535
recipe::next
recipe * next
Definition: recipe.h:24
recipe::skill
sstring skill
Definition: recipe.h:26
say.item
dictionary item
Definition: say.py:149
treasure
Definition: treasure.h:63
artifact
Definition: artifact.h:14
diamondslots.cost
int cost
Definition: diamondslots.py:21
build_stringlist
static void build_stringlist(const char *str, char ***result_list, size_t *result_size)
Definition: recipe.cpp:861
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.cpp:574
recipe_get_face
const Face * recipe_get_face(const recipe *rp)
Definition: recipe.cpp:920
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
object.h
llevDebug
@ llevDebug
Definition: logger.h:13
legal_artifact_combination
int legal_artifact_combination(const object *op, const artifact *art)
Definition: artifact.cpp:252
recipe::cauldron
sstring cauldron
Definition: recipe.h:27
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.cpp:102
recipe::title
sstring title
Definition: recipe.h:11