Crossfire Server, Branches 1.12  R18729
recipe.c
Go to the documentation of this file.
1 /*
2  CrossFire, A Multiplayer game for X-windows
3 
4  Copyright (C) 2001-2006 Crossfire Development Team
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20  The authors can be reached via e-mail at crossfire-devel@real-time.com
21 */
22 
44 #include <stdlib.h>
45 #include <global.h>
46 #include <object.h>
47 #include <ctype.h>
48 
49 static void build_stringlist(const char *str, char ***result_list, size_t *result_size);
50 static void check_formulae(void);
51 
54 
63 static recipelist *init_recipelist(void) {
64  recipelist *tl = (recipelist *)malloc(sizeof(recipelist));
65  if (tl == NULL)
67  tl->total_chance = 0;
68  tl->number = 0;
69  tl->items = NULL;
70  tl->next = NULL;
71  return tl;
72 }
73 
82 static recipe *get_empty_formula(void) {
83  recipe *t = (recipe *)malloc(sizeof(recipe));
84  if (t == NULL)
86  t->chance = 0;
87  t->index = 0;
88  t->transmute = 0;
89  t->yield = 0;
90  t->diff = 0;
91  t->exp = 0;
92  t->keycode = NULL;
93  t->title = NULL;
94  t->arch_names = 0;
95  t->arch_name = NULL;
96  t->skill = NULL;
97  t->cauldron = NULL;
98  t->ingred = NULL;
99  t->next = NULL;
100  return t;
101 }
102 
113  recipelist *fl = formulalist;
114  int number = i;
115 
116  while (fl && number > 1) {
117  if (!(fl = fl->next))
118  break;
119  number--;
120  }
121  return fl;
122 }
123 
134 static int check_recipe(const recipe *rp) {
135  size_t i;
136  int result;
137 
138  result = 1;
139  for (i = 0; i < rp->arch_names; i++) {
140  if (find_archetype(rp->arch_name[i]) != NULL) {
141  artifact *art = locate_recipe_artifact(rp, i);
142 
143  if (!art && strcmp(rp->title, "NONE") != 0) {
144  LOG(llevError, "\nWARNING: Formula %s of %s has no artifact.\n", rp->arch_name[i], rp->title);
145  result = 0;
146  }
147  } else {
148  LOG(llevError, "\nWARNING: Can't find archetype %s for formula %s\n", rp->arch_name[i], rp->title);
149  result = 0;
150  }
151  }
152 
153  return result;
154 }
155 
159 void init_formulae(void) {
160  static int has_been_done = 0;
161  FILE *fp;
162  char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
163  recipe *formula = NULL;
164  recipelist *fl = init_recipelist();
165  linked_char *tmp;
166  int value, comp;
167 
168  if (!formulalist)
169  formulalist = fl;
170 
171  if (has_been_done)
172  return;
173  else
174  has_been_done = 1;
175 
176  snprintf(filename, sizeof(filename), "%s/formulae", settings.datadir);
177  LOG(llevDebug, "Reading alchemical formulae from %s...\n", filename);
178  if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
179  LOG(llevError, "Can't open %s.\n", filename);
180  return;
181  }
182 
183  while (fgets(buf, MAX_BUF, fp) != NULL) {
184  if (*buf == '#')
185  continue;
186  if ((cp = strchr(buf, '\n')) != NULL)
187  *cp = '\0';
188  cp = buf;
189  while (*cp == ' ') /* Skip blanks */
190  cp++;
191 
192  if (!strncmp(cp, "Object", 6)) {
193  formula = get_empty_formula();
194  formula->title = add_string(strchr(cp, ' ')+1);
195  } else if (!strncmp(cp, "keycode", 7)) {
196  formula->keycode = add_string(strchr(cp, ' ')+1);
197  } else if (sscanf(cp, "trans %d", &value)) {
198  formula->transmute = value;
199  } else if (sscanf(cp, "yield %d", &value)) {
200  formula->yield = value;
201  } else if (sscanf(cp, "chance %d", &value)) {
202  formula->chance = value;
203  } else if (sscanf(cp, "exp %d", &value)) {
204  formula->exp = value;
205  } else if (sscanf(cp, "diff %d", &value)) {
206  formula->diff = value;
207  } else if (!strncmp(cp, "ingred", 6)) {
208  int numb_ingred = 1;
209  cp = strchr(cp, ' ')+1;
210  do {
211  if ((next = strchr(cp, ',')) != NULL) {
212  *(next++) = '\0';
213  numb_ingred++;
214  }
215  tmp = (linked_char *)malloc(sizeof(linked_char));
216  tmp->name = add_string(cp);
217  tmp->next = formula->ingred;
218  formula->ingred = tmp;
219  /* each ingredient's ASCII value is coadded. Later on this
220  * value will be used allow us to search the formula lists
221  * quickly for the right recipe.
222  */
223  formula->index += strtoint(cp);
224  } while ((cp = next) != NULL);
225  /* now find the correct (# of ingred ordered) formulalist */
226  fl = formulalist;
227  while (numb_ingred != 1) {
228  if (!fl->next)
229  fl->next = init_recipelist();
230  fl = fl->next;
231  numb_ingred--;
232  }
233  fl->total_chance += formula->chance;
234  fl->number++;
235  formula->next = fl->items;
236  fl->items = formula;
237  } else if (!strncmp(cp, "arch", 4)) {
238  build_stringlist(strchr(cp, ' ')+1, &formula->arch_name, &formula->arch_names);
239  check_recipe(formula);
240  } else if (!strncmp(cp, "skill", 5)) {
241  formula->skill = add_string(strchr(cp, ' ')+1);
242  } else if (!strncmp(cp, "cauldron", 8)) {
243  formula->cauldron = add_string(strchr(cp, ' ')+1);
244  } else
245  LOG(llevError, "Unknown input in file %s: %s\n", filename, buf);
246  }
247  LOG(llevDebug, "done.\n");
248  close_and_delete(fp, comp);
249  /* Lastly, lets check for problems in formula we got */
250  check_formulae();
251 }
252 
265 static void check_formulae(void) {
266  recipelist *fl;
267  recipe *check, *formula;
268  int numb = 1;
269 
270  LOG(llevDebug, "Checking formulae lists...\n");
271 
272  for (fl = formulalist; fl != NULL; fl = fl->next) {
273  for (formula = fl->items; formula != NULL; formula = formula->next)
274  for (check = formula->next; check != NULL; check = check->next)
275  if (check->index == formula->index && strcmp(check->cauldron, formula->cauldron) == 0) {
276  /* if the recipes don't have the same facility, then no issue anyway. */
277  LOG(llevError, " ERROR: On %d ingred list:\n", numb);
278  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);
279  }
280  numb++;
281  }
282 
283  LOG(llevDebug, "done checking.\n");
284 }
285 
293 void dump_alchemy(void) {
294  recipelist *fl = formulalist;
295  recipe *formula = NULL;
296  linked_char *next;
297  int num_ingred = 1;
298 
299  fprintf(logfile, "\n");
300  while (fl) {
301  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);
302  for (formula = fl->items; formula != NULL; formula = formula->next) {
303  artifact *art = NULL;
304  char buf[MAX_BUF];
305  size_t i;
306 
307  for (i = 0; i < formula->arch_names; i++) {
308  const char *string = formula->arch_name[i];
309 
310  if (find_archetype(string) != NULL) {
311  art = locate_recipe_artifact(formula, i);
312  if (!art && strcmp(formula->title, "NONE"))
313  LOG(llevError, "Formula %s has no artifact\n", formula->title);
314  else {
315  if (strcmp(formula->title, "NONE"))
316  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
317  else
318  snprintf(buf, sizeof(buf), "%s", string);
319  fprintf(logfile, "%-30s(%d) bookchance %3d ", buf, formula->index, formula->chance);
320  fprintf(logfile, "skill %s", formula->skill);
321  fprintf(logfile, "\n");
322  if (formula->ingred != NULL) {
323  int nval = 0, tval = 0;
324  fprintf(logfile, "\tIngred: ");
325  for (next = formula->ingred; next != NULL; next = next->next) {
326  if (nval != 0)
327  fprintf(logfile, ",");
328  fprintf(logfile, "%s(%d)", next->name, (nval = strtoint(next->name)));
329  tval += nval;
330  }
331  fprintf(logfile, "\n");
332  if (tval != formula->index)
333  fprintf(logfile, "WARNING:ingredient list and formula values not equal.\n");
334  }
335  if (formula->skill != NULL)
336  fprintf(logfile, "\tSkill Required: %s", formula->skill);
337  if (formula->cauldron != NULL)
338  fprintf(logfile, "\tCauldron: %s\n", formula->cauldron);
339  fprintf(logfile, "\tDifficulty: %d\t Exp: %d\n", formula->diff, formula->exp);
340  }
341  } else
342  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
343  }
344  }
345  fprintf(logfile, "\n");
346  fl = fl->next;
347  num_ingred++;
348  }
349 }
350 
365 archetype *find_treasure_by_name(const treasure *t, const char *name, int depth) {
366  treasurelist *tl;
367  archetype *at;
368 
369  if (depth > 10)
370  return NULL;
371 
372  while (t != NULL) {
373  if (t->name != NULL) {
374  tl = find_treasurelist(t->name);
375  at = find_treasure_by_name(tl->items, name, depth+1);
376  if (at != NULL)
377  return at;
378  } else {
379  if (!strcasecmp(t->item->clone.name, name))
380  return t->item;
381  }
382  if (t->next_yes != NULL) {
383  at = find_treasure_by_name(t->next_yes, name, depth);
384  if (at != NULL)
385  return at;
386  }
387  if (t->next_no != NULL) {
388  at = find_treasure_by_name(t->next_no, name, depth);
389  if (at != NULL)
390  return at;
391  }
392  t = t->next;
393  }
394  return NULL;
395 }
396 
416 static long find_ingred_cost(const char *name) {
417  archetype *at;
418  archetype *at2;
419  artifactlist *al;
420  artifact *art;
421  long mult;
422  char *cp;
423  char part1[100];
424  char part2[100];
425 
426  /* same as atoi(), but skip number */
427  mult = 0;
428  while (isdigit(*name)) {
429  mult = 10*mult+(*name-'0');
430  name++;
431  }
432  if (mult > 0)
433  name++;
434  else
435  mult = 1;
436  /* first, try to match the name of an archetype */
437  for (at = first_archetype; at != NULL; at = at->next) {
438  if (at->clone.title != NULL) {
439  /* inefficient, but who cares? */
440  snprintf(part1, sizeof(part1), "%s %s", at->clone.name, at->clone.title);
441  if (!strcasecmp(part1, name))
442  return mult*at->clone.value;
443  }
444  if (!strcasecmp(at->clone.name, name))
445  return mult*at->clone.value;
446  }
447  /* second, try to match an artifact ("arch of something") */
448  cp = strstr(name, " of ");
449  if (cp != NULL) {
450  strcpy(part1, name);
451  part1[cp-name] = '\0';
452  strcpy(part2, cp+4);
453  /* find the first archetype matching the first part of the name */
454  for (at = first_archetype; at != NULL; at = at->next)
455  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL)
456  break;
457  if (at != NULL) {
458  /* find the first artifact derived from that archetype (same type) */
459  for (al = first_artifactlist; al != NULL; al = al->next)
460  if (al->type == at->clone.type) {
461  for (art = al->items; art != NULL; art = art->next)
462  if (!strcasecmp(art->item->name, part2))
463  return mult*at->clone.value*art->item->value;
464  }
465  }
466  }
467  /* third, try to match a body part ("arch's something") */
468  cp = strstr(name, "'s ");
469  if (cp != NULL) {
470  strcpy(part1, name);
471  part1[cp-name] = '\0';
472  strcpy(part2, cp+3);
473  /* examine all archetypes matching the first part of the name */
474  for (at = first_archetype; at != NULL; at = at->next)
475  if (!strcasecmp(at->clone.name, part1) && at->clone.title == NULL) {
476  if (at->clone.randomitems != NULL) {
477  at2 = find_treasure_by_name(at->clone.randomitems->items, part2, 0);
478  if (at2 != NULL)
479  return mult*at2->clone.value*isqrt(at->clone.level*2);
480  }
481  }
482  }
483  /* failed to find any matching items -- formula should be checked */
484  return -1;
485 }
486 
495 void dump_alchemy_costs(void) {
496  recipelist *fl = formulalist;
497  recipe *formula = NULL;
498  linked_char *next;
499  int num_ingred = 1;
500  int num_errors = 0;
501  long cost;
502  long tcost;
503 
504  fprintf(logfile, "\n");
505  while (fl) {
506  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);
507  for (formula = fl->items; formula != NULL; formula = formula->next) {
508  artifact *art = NULL;
509  archetype *at = NULL;
510  char buf[MAX_BUF];
511  size_t i;
512 
513  for (i = 0; i < formula->arch_names; i++) {
514  const char *string = formula->arch_name[i];
515 
516  if ((at = find_archetype(string)) != NULL) {
517  art = locate_recipe_artifact(formula, i);
518  if (!art && strcmp(formula->title, "NONE"))
519  LOG(llevError, "Formula %s has no artifact\n", formula->title);
520  else {
521  if (!strcmp(formula->title, "NONE"))
522  snprintf(buf, sizeof(buf), "%s", string);
523  else
524  snprintf(buf, sizeof(buf), "%s of %s", string, formula->title);
525  fprintf(logfile, "\n%-40s bookchance %3d skill %s\n", buf, formula->chance, formula->skill);
526  if (formula->ingred != NULL) {
527  tcost = 0;
528  for (next = formula->ingred; next != NULL; next = next->next) {
529  cost = find_ingred_cost(next->name);
530  if (cost < 0)
531  num_errors++;
532  fprintf(logfile, "\t%-33s%5ld\n", next->name, cost);
533  if (cost < 0 || tcost < 0)
534  tcost = -1;
535  else
536  tcost += cost;
537  }
538  if (art != NULL && art->item != NULL)
539  cost = at->clone.value*art->item->value;
540  else
541  cost = at->clone.value;
542  fprintf(logfile, "\t\tBuying result costs: %5ld", cost);
543  if (formula->yield > 1) {
544  fprintf(logfile, " to %ld (max %d items)\n", cost*formula->yield, formula->yield);
545  cost = cost*(formula->yield+1L)/2L;
546  } else
547  fprintf(logfile, "\n");
548  fprintf(logfile, "\t\tIngredients cost: %5ld\n\t\tComment: ", tcost);
549  if (tcost < 0)
550  fprintf(logfile, "Could not find some ingredients. Check the formula!\n");
551  else if (tcost > cost)
552  fprintf(logfile, "Ingredients are much too expensive. Useless formula.\n");
553  else if (tcost*2L > cost)
554  fprintf(logfile, "Ingredients are too expensive.\n");
555  else if (tcost*10L < cost)
556  fprintf(logfile, "Ingredients are too cheap.\n");
557  else
558  fprintf(logfile, "OK.\n");
559  }
560  }
561  } else
562  LOG(llevError, "Can't find archetype:%s for formula %s\n", string, formula->title);
563  }
564  }
565  fprintf(logfile, "\n");
566  fl = fl->next;
567  num_ingred++;
568  }
569  if (num_errors > 0)
570  fprintf(logfile, "WARNING: %d objects required by the formulae do not exist in the game.\n", num_errors);
571 }
572 
581 static const char *ingred_name(const char *name) {
582  const char *cp = name;
583 
584  if (atoi(cp))
585  cp = strchr(cp, ' ')+1;
586  return cp;
587 }
588 
597 static int numb_ingred(const char *buf) {
598  int numb;
599 
600  if ((numb = atoi(buf)))
601  return numb;
602  else
603  return 1;
604 }
605 
616 int strtoint(const char *buf) {
617  const char *cp = ingred_name(buf);
618  int val = 0, len = strlen(cp), mult = numb_ingred(buf);
619 
620  while (len) {
621  val += tolower(*cp);
622  cp++; len--;
623  }
624  return val*mult;
625 }
626 
637 artifact *locate_recipe_artifact(const recipe *rp, size_t idx) {
638  object *item = create_archetype(rp->arch_name[idx]);
639  artifactlist *at = NULL;
640  artifact *art = NULL;
641 
642  if (!item)
643  return (artifact *)NULL;
644 
645  if ((at = find_artifactlist(item->type)))
646  for (art = at->items; art; art = art->next)
647  if (!strcmp(art->item->name, rp->title) && legal_artifact_combination(item, art))
648  break;
649 
650  free_object(item);
651 
652  return art;
653 }
654 
662  recipelist *fl = NULL;
663  int number = 0, roll = 0;
664 
665  /* first, determine # of recipelist we have */
666  for (fl = get_formulalist(1); fl; fl = fl->next)
667  number++;
668 
669  /* now, randomly choose one */
670  if (number > 0)
671  roll = RANDOM()%number;
672 
673  fl = get_formulalist(1);
674  while (roll && fl) {
675  if (fl->next)
676  fl = fl->next;
677  else
678  break;
679  roll--;
680  }
681  if (!fl) /* failed! */
682  LOG(llevError, "get_random_recipelist(): no recipelists found!\n");
683  else if (fl->total_chance == 0)
684  fl = get_random_recipelist();
685 
686  return fl;
687 }
688 
698  recipelist *fl = rpl;
699  recipe *rp = NULL;
700  int r = 0;
701 
702  /* looks like we have to choose a random one */
703  if (fl == NULL)
704  if ((fl = get_random_recipelist()) == NULL)
705  return rp;
706 
707  if (fl->total_chance > 0) {
708  r = RANDOM()%fl->total_chance;
709  for (rp = fl->items; rp; rp = rp->next) {
710  r -= rp->chance;
711  if (r < 0)
712  break;
713  }
714  }
715  return rp;
716 }
717 
721 void free_all_recipes(void) {
722  recipelist *fl = formulalist, *flnext;
723  recipe *formula = NULL, *next;
724  linked_char *lchar, *charnext;
725 
726  LOG(llevDebug, "Freeing all the recipes\n");
727  for (fl = formulalist; fl != NULL; fl = flnext) {
728  flnext = fl->next;
729 
730  for (formula = fl->items; formula != NULL; formula = next) {
731  next = formula->next;
732 
733  free(formula->arch_name[0]);
734  free(formula->arch_name);
735  if (formula->title)
736  free_string(formula->title);
737  if (formula->skill)
738  free_string(formula->skill);
739  if (formula->cauldron)
740  free_string(formula->cauldron);
741  for (lchar = formula->ingred; lchar; lchar = charnext) {
742  charnext = lchar->next;
743  free_string(lchar->name);
744  free(lchar);
745  }
746  free(formula);
747  }
748  free(fl);
749  }
750  formulalist = NULL;
751 }
752 
764 static void build_stringlist(const char *str, char ***result_list, size_t *result_size) {
765  char *dup;
766  char *p;
767  size_t size;
768  size_t i;
769 
770  dup = strdup_local(str);
771  if (dup == NULL)
773 
774  size = 0;
775  for (p = strtok(dup, ","); p != NULL; p = strtok(NULL, ","))
776  size++;
777 
778  *result_list = malloc(size*sizeof(*result_list));
779  if (*result_list == NULL)
781  *result_size = size;
782 
783  for (i = 0; i < size; i++) {
784  (*result_list)[i] = dup;
785  dup = dup+strlen(dup)+1;
786  }
787 }
EXTERN FILE * logfile
Definition: global.h:220
int legal_artifact_combination(object *op, artifact *art)
Definition: treasure.c:1849
static void check_formulae(void)
Definition: recipe.c:265
const char * title
Definition: recipe.h:11
archetype * find_archetype(const char *name)
Definition: arch.c:700
int diff
Definition: recipe.h:16
#define OUT_OF_MEMORY
Definition: define.h:94
archetype * find_treasure_by_name(const treasure *t, const char *name, int depth)
Definition: recipe.c:365
static void build_stringlist(const char *str, char ***result_list, size_t *result_size)
Definition: recipe.c:764
recipe * get_random_recipe(recipelist *rpl)
Definition: recipe.c:697
struct recipeliststruct * next
Definition: recipe.h:34
static int check_recipe(const recipe *rp)
Definition: recipe.c:134
int yield
Definition: recipe.h:21
struct artifactstruct * items
Definition: artifact.h:52
treasurelist * find_treasurelist(const char *name)
Definition: treasure.c:295
void free_string(sstring str)
Definition: shstr.c:272
struct treasureliststruct * randomitems
Definition: object.h:236
object clone
Definition: object.h:326
linked_char * ingred
Definition: recipe.h:22
static int numb_ingred(const char *buf)
Definition: recipe.c:597
static recipelist * init_recipelist(void)
Definition: recipe.c:63
void close_and_delete(FILE *fp, int compressed)
Definition: porting.c:748
int transmute
Definition: recipe.h:19
static recipelist * get_random_recipelist(void)
Definition: recipe.c:661
Definition: object.h:321
void dump_alchemy_costs(void)
Definition: recipe.c:495
struct archt * item
Definition: treasure.h:93
void init_formulae(void)
Definition: recipe.c:159
int chance
Definition: recipe.h:14
const char * title
Definition: object.h:170
struct artifactliststruct * next
Definition: artifact.h:51
object * create_archetype(const char *name)
Definition: arch.c:625
artifactlist * find_artifactlist(int type)
Definition: treasure.c:1431
char ** arch_name
Definition: recipe.h:13
static const char * ingred_name(const char *name)
Definition: recipe.c:581
int total_chance
Definition: recipe.h:31
void dump_alchemy(void)
Definition: recipe.c:293
struct linked_char * next
Definition: global.h:161
int strtoint(const char *buf)
Definition: recipe.c:616
const char * name
Definition: object.h:167
void fatal(int err)
Definition: glue.c:60
struct treasurestruct * next_no
Definition: treasure.h:97
EXTERN artifactlist * first_artifactlist
Definition: global.h:194
char * strdup_local(const char *str)
Definition: porting.c:310
static recipelist * formulalist
Definition: recipe.c:53
int index
Definition: recipe.h:18
#define MAX_BUF
Definition: define.h:81
const char * keycode
Definition: recipe.h:24
struct treasurestruct * items
Definition: treasure.h:119
#define tolower(C)
Definition: c_new.c:42
void free_all_recipes(void)
Definition: recipe.c:721
int exp
Definition: recipe.h:17
const char * datadir
Definition: global.h:334
const char * cauldron
Definition: recipe.h:26
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
const char * name
Definition: global.h:160
struct treasurestruct * next_yes
Definition: treasure.h:96
const char * skill
Definition: recipe.h:25
size_t arch_names
Definition: recipe.h:12
struct Settings settings
Definition: init.c:48
int isqrt(int n)
Definition: porting.c:573
struct archt * next
Definition: object.h:323
struct recipestruct * next
Definition: recipe.h:23
sstring add_string(const char *str)
Definition: shstr.c:116
int strcasecmp(const char *s1, const char *s2)
Definition: porting.c:434
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
artifact * locate_recipe_artifact(const recipe *rp, size_t idx)
Definition: recipe.c:637
static long find_ingred_cost(const char *name)
Definition: recipe.c:416
object * item
Definition: artifact.h:38
static recipe * get_empty_formula(void)
Definition: recipe.c:82
void free_object(object *ob)
Definition: object.c:1238
struct treasurestruct * next
Definition: treasure.h:95
sint16 level
Definition: object.h:202
const char * name
Definition: treasure.h:94
EXTERN archetype * first_archetype
Definition: global.h:195
FILE * open_and_uncompress(const char *name, int flag, int *compressed)
Definition: porting.c:724
sint32 value
Definition: object.h:201
struct recipestruct * items
Definition: recipe.h:33
recipelist * get_formulalist(int i)
Definition: recipe.c:112
uint8 type
Definition: object.h:189
struct artifactstruct * next
Definition: artifact.h:41